19911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton/* 29911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * Copyright (C) 2010 The Android Open Source Project 39911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * 49911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * Licensed under the Apache License, Version 2.0 (the "License"); 59911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * you may not use this file except in compliance with the License. 69911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * You may obtain a copy of the License at 79911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * 89911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * http://www.apache.org/licenses/LICENSE-2.0 99911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * 109911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * Unless required by applicable law or agreed to in writing, software 119911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * distributed under the License is distributed on an "AS IS" BASIS, 129911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * See the License for the specific language governing permissions and 149911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * limitations under the License. 159911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 169911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 179911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamiltonpackage android.content; 189911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 199911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamiltonimport android.database.ContentObserver; 209911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamiltonimport android.os.Handler; 21a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackbornimport android.util.DebugUtils; 22a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 23a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackbornimport java.io.FileDescriptor; 24a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackbornimport java.io.PrintWriter; 259911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 269911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton/** 279525f2a72e2786f1b53927878dd8234859ea5c39Mark Doliner * A class that performs asynchronous loading of data. While Loaders are active 289911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * they should monitor the source of their data and deliver new results when the contents 299567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * change. See {@link android.app.LoaderManager} for more detail. 309911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * 31247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * <p><b>Note on threading:</b> Clients of loaders should as a rule perform 32247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * any calls on to a Loader from the main thread of their process (that is, 33247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * the thread the Activity callbacks and other things occur on). Subclasses 34247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * of Loader (such as {@link AsyncTaskLoader}) will often perform their work 35247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * in a separate thread, but when delivering their results this too should 36247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * be done on the main thread.</p> 37247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * 38a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * <p>Subclasses generally must implement at least {@link #onStartLoading()}, 399567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * {@link #onStopLoading()}, {@link #onForceLoad()}, and {@link #onReset()}.</p> 409567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * 419567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * <p>Most implementations should not derive directly from this class, but 429567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * instead inherit from {@link AsyncTaskLoader}.</p> 43b54e7a3d9f60ac605f404f9eb3c5e92ca51bbd23Joe Fernandez * 44b54e7a3d9f60ac605f404f9eb3c5e92ca51bbd23Joe Fernandez * <div class="special reference"> 45b54e7a3d9f60ac605f404f9eb3c5e92ca51bbd23Joe Fernandez * <h3>Developer Guides</h3> 46b54e7a3d9f60ac605f404f9eb3c5e92ca51bbd23Joe Fernandez * <p>For more information about using loaders, read the 47b54e7a3d9f60ac605f404f9eb3c5e92ca51bbd23Joe Fernandez * <a href="{@docRoot}guide/topics/fundamentals/loaders.html">Loaders</a> developer guide.</p> 48b54e7a3d9f60ac605f404f9eb3c5e92ca51bbd23Joe Fernandez * </div> 49a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * 509911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * @param <D> The result returned when the load is complete 519911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 52a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackbornpublic class Loader<D> { 539911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton int mId; 549911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton OnLoadCompleteListener<D> mListener; 55b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown OnLoadCanceledListener<D> mOnLoadCanceledListener; 569911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton Context mContext; 57a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn boolean mStarted = false; 58260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn boolean mAbandoned = false; 59a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn boolean mReset = true; 600e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn boolean mContentChanged = false; 61ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn boolean mProcessingChange = false; 629911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 637871badd5d4d29d80207e9cc09a0681f26a151d0Dianne Hackborn /** 647871badd5d4d29d80207e9cc09a0681f26a151d0Dianne Hackborn * An implementation of a ContentObserver that takes care of connecting 657871badd5d4d29d80207e9cc09a0681f26a151d0Dianne Hackborn * it to the Loader to have the loader re-load its data when the observer 667871badd5d4d29d80207e9cc09a0681f26a151d0Dianne Hackborn * is told it has changed. You do not normally need to use this yourself; 677871badd5d4d29d80207e9cc09a0681f26a151d0Dianne Hackborn * it is used for you by {@link CursorLoader} to take care of executing 687871badd5d4d29d80207e9cc09a0681f26a151d0Dianne Hackborn * an update when the cursor's backing data changes. 697871badd5d4d29d80207e9cc09a0681f26a151d0Dianne Hackborn */ 709911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public final class ForceLoadContentObserver extends ContentObserver { 719911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public ForceLoadContentObserver() { 729911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton super(new Handler()); 739911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 749911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 759911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton @Override 769911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public boolean deliverSelfNotifications() { 779911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton return true; 789911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 799911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 809911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton @Override 819911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public void onChange(boolean selfChange) { 82ec37c88570bdd1b94309ad613395295f13449c3fMakoto Onuki onContentChanged(); 839911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 849911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 859911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 867871badd5d4d29d80207e9cc09a0681f26a151d0Dianne Hackborn /** 877871badd5d4d29d80207e9cc09a0681f26a151d0Dianne Hackborn * Interface that is implemented to discover when a Loader has finished 887871badd5d4d29d80207e9cc09a0681f26a151d0Dianne Hackborn * loading its data. You do not normally need to implement this yourself; 897871badd5d4d29d80207e9cc09a0681f26a151d0Dianne Hackborn * it is used in the implementation of {@link android.app.LoaderManager} 907871badd5d4d29d80207e9cc09a0681f26a151d0Dianne Hackborn * to find out when a Loader it is managing has completed so that this can 917871badd5d4d29d80207e9cc09a0681f26a151d0Dianne Hackborn * be reported to its client. This interface should only be used if a 927871badd5d4d29d80207e9cc09a0681f26a151d0Dianne Hackborn * Loader is not being used in conjunction with LoaderManager. 937871badd5d4d29d80207e9cc09a0681f26a151d0Dianne Hackborn */ 949911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public interface OnLoadCompleteListener<D> { 959911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 969911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * Called on the thread that created the Loader when the load is complete. 979911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * 989911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * @param loader the loader that completed the load 999911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * @param data the result of the load 1009911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 1019911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public void onLoadComplete(Loader<D> loader, D data); 1029911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1039911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 1049911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 105b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * Interface that is implemented to discover when a Loader has been canceled 106b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * before it finished loading its data. You do not normally need to implement 107b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * this yourself; it is used in the implementation of {@link android.app.LoaderManager} 108b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * to find out when a Loader it is managing has been canceled so that it 109b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * can schedule the next Loader. This interface should only be used if a 110b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * Loader is not being used in conjunction with LoaderManager. 111b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown */ 112b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown public interface OnLoadCanceledListener<D> { 113b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown /** 114b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * Called on the thread that created the Loader when the load is canceled. 115b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * 116b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * @param loader the loader that canceled the load 117b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown */ 118b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown public void onLoadCanceled(Loader<D> loader); 119b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown } 120b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown 121b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown /** 1229567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * Stores away the application context associated with context. 1239567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * Since Loaders can be used across multiple activities it's dangerous to 1249567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * store the context directly; always use {@link #getContext()} to retrieve 1259567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * the Loader's Context, don't use the constructor argument directly. 1269567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * The Context returned by {@link #getContext} is safe to use across 1279567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * Activity instances. 1289911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * 1299911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * @param context used to retrieve the application context. 1309911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 1319911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public Loader(Context context) { 1329911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton mContext = context.getApplicationContext(); 1339911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1349911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 1359911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 1369911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * Sends the result of the load to the registered listener. Should only be called by subclasses. 1379911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * 138247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * Must be called from the process's main thread. 1399911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * 1409911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * @param data the result of the load 1419911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 1429911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public void deliverResult(D data) { 1439911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton if (mListener != null) { 1449911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton mListener.onLoadComplete(this, data); 1459911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1469911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1479911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 1489911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 149b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * Informs the registered {@link OnLoadCanceledListener} that the load has been canceled. 150b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * Should only be called by subclasses. 151b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * 152b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * Must be called from the process's main thread. 153b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown */ 154b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown public void deliverCancellation() { 155b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown if (mOnLoadCanceledListener != null) { 156b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown mOnLoadCanceledListener.onLoadCanceled(this); 157b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown } 158b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown } 159b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown 160b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown /** 1619911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * @return an application context retrieved from the Context passed to the constructor. 1629911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 1639911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public Context getContext() { 1649911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton return mContext; 1659911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1669911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 1679911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 1689911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * @return the ID of this loader 1699911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 1709911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public int getId() { 1719911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton return mId; 1729911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1739911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 1749911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 175247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * Registers a class that will receive callbacks when a load is complete. 176247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * The callback will be called on the process's main thread so it's safe to 177247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * pass the results to widgets. 178ec37c88570bdd1b94309ad613395295f13449c3fMakoto Onuki * 179247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * <p>Must be called from the process's main thread. 1809911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 1819911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public void registerListener(int id, OnLoadCompleteListener<D> listener) { 1829911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton if (mListener != null) { 1839911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton throw new IllegalStateException("There is already a listener registered"); 1849911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1859911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton mListener = listener; 1869911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton mId = id; 1879911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1889911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 1899911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 190247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * Remove a listener that was previously added with {@link #registerListener}. 191247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * 192247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * Must be called from the process's main thread. 1939911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 1949911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public void unregisterListener(OnLoadCompleteListener<D> listener) { 1959911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton if (mListener == null) { 1969911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton throw new IllegalStateException("No listener register"); 1979911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1989911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton if (mListener != listener) { 1999911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton throw new IllegalArgumentException("Attempting to unregister the wrong listener"); 2009911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 2019911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton mListener = null; 2029911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 2039911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 2049911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 205b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * Registers a listener that will receive callbacks when a load is canceled. 206b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * The callback will be called on the process's main thread so it's safe to 207b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * pass the results to widgets. 208b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * 209b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * Must be called from the process's main thread. 210b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * 211b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * @param listener The listener to register. 212b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown */ 213b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown public void registerOnLoadCanceledListener(OnLoadCanceledListener<D> listener) { 214b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown if (mOnLoadCanceledListener != null) { 215b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown throw new IllegalStateException("There is already a listener registered"); 216b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown } 217b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown mOnLoadCanceledListener = listener; 218b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown } 219b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown 220b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown /** 221b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * Unregisters a listener that was previously added with 222b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * {@link #registerOnLoadCanceledListener}. 223b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * 224b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * Must be called from the process's main thread. 225b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * 226b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * @param listener The listener to unregister. 227b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown */ 228b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown public void unregisterOnLoadCanceledListener(OnLoadCanceledListener<D> listener) { 229b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown if (mOnLoadCanceledListener == null) { 230b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown throw new IllegalStateException("No listener register"); 231b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown } 232b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown if (mOnLoadCanceledListener != listener) { 233b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown throw new IllegalArgumentException("Attempting to unregister the wrong listener"); 234b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown } 235b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown mOnLoadCanceledListener = null; 236b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown } 237b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown 238b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown /** 239a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * Return whether this load has been started. That is, its {@link #startLoading()} 240a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * has been called and no calls to {@link #stopLoading()} or 241a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * {@link #reset()} have yet been made. 242a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn */ 243a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn public boolean isStarted() { 244a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn return mStarted; 245a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 246a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 247a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn /** 248260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * Return whether this loader has been abandoned. In this state, the 249260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * loader <em>must not</em> report any new data, and <em>must</em> keep 250260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * its last reported data valid until it is finally reset. 251260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn */ 252260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn public boolean isAbandoned() { 253260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn return mAbandoned; 254260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn } 255260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn 256260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn /** 257a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * Return whether this load has been reset. That is, either the loader 258a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * has not yet been started for the first time, or its {@link #reset()} 259a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * has been called. 260a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn */ 261a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn public boolean isReset() { 262a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn return mReset; 263a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 264a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 265a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn /** 2662c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * This function will normally be called for you automatically by 2672c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * {@link android.app.LoaderManager} when the associated fragment/activity 2682c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * is being started. When using a Loader with {@link android.app.LoaderManager}, 2692c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * you <em>must not</em> call this method yourself, or you will conflict 2702c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * with its management of the Loader. 2712c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * 272247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * Starts an asynchronous load of the Loader's data. When the result 273247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * is ready the callbacks will be called on the process's main thread. 274247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * If a previous load has been completed and is still valid 275247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * the result may be passed to the callbacks immediately. 276247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * The loader will monitor the source of 277247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * the data set and may deliver future callbacks if the source changes. 278247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * Calling {@link #stopLoading} will stop the delivery of callbacks. 2799911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * 280a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * <p>This updates the Loader's internal state so that 281a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * {@link #isStarted()} and {@link #isReset()} will return the correct 282a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * values, and then calls the implementation's {@link #onStartLoading()}. 283a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * 284247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * <p>Must be called from the process's main thread. 285a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn */ 2860e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn public final void startLoading() { 287a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn mStarted = true; 288a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn mReset = false; 289260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn mAbandoned = false; 290a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn onStartLoading(); 291a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 292a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 293a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn /** 294a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * Subclasses must implement this to take care of loading their data, 295a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * as per {@link #startLoading()}. This is not called by clients directly, 296a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * but as a result of a call to {@link #startLoading()}. 2979911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 298a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn protected void onStartLoading() { 299a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 3009911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 3019911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 302b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * Attempt to cancel the current load task. 303b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * Must be called on the main thread of the process. 304b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * 305b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * <p>Cancellation is not an immediate operation, since the load is performed 306b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * in a background thread. If there is currently a load in progress, this 307b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * method requests that the load be canceled, and notes this is the case; 308b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * once the background thread has completed its work its remaining state 309b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * will be cleared. If another load request comes in during this time, 310b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * it will be held until the canceled load is complete. 311b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * 312b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * @return Returns <tt>false</tt> if the task could not be canceled, 313b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * typically because it has already completed normally, or 314b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * because {@link #startLoading()} hasn't been called; returns 315b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * <tt>true</tt> otherwise. When <tt>true</tt> is returned, the task 316b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * is still running and the {@link OnLoadCanceledListener} will be called 317b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * when the task completes. 318b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown */ 319b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown public boolean cancelLoad() { 320b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown return onCancelLoad(); 321b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown } 322b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown 323b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown /** 324b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * Subclasses must implement this to take care of requests to {@link #cancelLoad()}. 325b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * This will always be called from the process's main thread. 326b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * 327b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * @return Returns <tt>false</tt> if the task could not be canceled, 328b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * typically because it has already completed normally, or 329b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * because {@link #startLoading()} hasn't been called; returns 330b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * <tt>true</tt> otherwise. When <tt>true</tt> is returned, the task 331b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * is still running and the {@link OnLoadCanceledListener} will be called 332b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown * when the task completes. 333b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown */ 334b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown protected boolean onCancelLoad() { 335b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown return false; 336b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown } 337b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown 338b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown /** 3399911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * Force an asynchronous load. Unlike {@link #startLoading()} this will ignore a previously 340a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * loaded data set and load a new one. This simply calls through to the 3410e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * implementation's {@link #onForceLoad()}. You generally should only call this 3420e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * when the loader is started -- that is, {@link #isStarted()} returns true. 343a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * 344247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * <p>Must be called from the process's main thread. 3459911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 346247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn public void forceLoad() { 347a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn onForceLoad(); 348a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 3499911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 3509911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 351a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * Subclasses must implement this to take care of requests to {@link #forceLoad()}. 352247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * This will always be called from the process's main thread. 353a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn */ 354a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn protected void onForceLoad() { 355a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 356a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 357a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn /** 3582c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * This function will normally be called for you automatically by 3592c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * {@link android.app.LoaderManager} when the associated fragment/activity 3602c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * is being stopped. When using a Loader with {@link android.app.LoaderManager}, 3612c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * you <em>must not</em> call this method yourself, or you will conflict 3622c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * with its management of the Loader. 3632c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * 3642c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * <p>Stops delivery of updates until the next time {@link #startLoading()} is called. 3650e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * Implementations should <em>not</em> invalidate their data at this point -- 3660e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * clients are still free to use the last data the loader reported. They will, 3670e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * however, typically stop reporting new data if the data changes; they can 3680e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * still monitor for changes, but must not report them to the client until and 3690e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * if {@link #startLoading()} is later called. 3709911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * 371a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * <p>This updates the Loader's internal state so that 372a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * {@link #isStarted()} will return the correct 373a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * value, and then calls the implementation's {@link #onStopLoading()}. 374a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * 375247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * <p>Must be called from the process's main thread. 3769911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 377247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn public void stopLoading() { 378a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn mStarted = false; 379a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn onStopLoading(); 380a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 381a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 382a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn /** 383a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * Subclasses must implement this to take care of stopping their loader, 384a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * as per {@link #stopLoading()}. This is not called by clients directly, 385a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * but as a result of a call to {@link #stopLoading()}. 386247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * This will always be called from the process's main thread. 387a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn */ 388a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn protected void onStopLoading() { 389a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 3909911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 3919911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 3922c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * This function will normally be called for you automatically by 3932c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * {@link android.app.LoaderManager} when restarting a Loader. When using 3942c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * a Loader with {@link android.app.LoaderManager}, 3952c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * you <em>must not</em> call this method yourself, or you will conflict 3962c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * with its management of the Loader. 3972c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * 398260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * Tell the Loader that it is being abandoned. This is called prior 399260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * to {@link #reset} to have it retain its current data but not report 400260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * any new data. 401260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn */ 402260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn public void abandon() { 403260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn mAbandoned = true; 404260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn onAbandon(); 405260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn } 406260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn 407260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn /** 408260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * Subclasses implement this to take care of being abandoned. This is 409260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * an optional intermediate state prior to {@link #onReset()} -- it means that 410260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * the client is no longer interested in any new data from the loader, 411260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * so the loader must not report any further updates. However, the 412260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * loader <em>must</em> keep its last reported data valid until the final 413260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * {@link #onReset()} happens. You can retrieve the current abandoned 414260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * state with {@link #isAbandoned}. 415260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn */ 416c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown protected void onAbandon() { 417260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn } 418260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn 419260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn /** 4202c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * This function will normally be called for you automatically by 4212c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * {@link android.app.LoaderManager} when destroying a Loader. When using 4222c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * a Loader with {@link android.app.LoaderManager}, 4232c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * you <em>must not</em> call this method yourself, or you will conflict 4242c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * with its management of the Loader. 4252c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * 426c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * Resets the state of the Loader. The Loader should at this point free 427c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * all of its resources, since it may never be called again; however, its 428c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * {@link #startLoading()} may later be called at which point it must be 429c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * able to start running again. 4309911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * 431a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * <p>This updates the Loader's internal state so that 432a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * {@link #isStarted()} and {@link #isReset()} will return the correct 433a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * values, and then calls the implementation's {@link #onReset()}. 434a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * 435247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * <p>Must be called from the process's main thread. 4369911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 437247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn public void reset() { 438a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn onReset(); 439a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn mReset = true; 440a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn mStarted = false; 441260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn mAbandoned = false; 4420e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn mContentChanged = false; 443ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn mProcessingChange = false; 444c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } 445c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn 446c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn /** 447a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * Subclasses must implement this to take care of resetting their loader, 448a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * as per {@link #reset()}. This is not called by clients directly, 449a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * but as a result of a call to {@link #reset()}. 450247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * This will always be called from the process's main thread. 451c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn */ 452a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn protected void onReset() { 453c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } 454ec37c88570bdd1b94309ad613395295f13449c3fMakoto Onuki 455ec37c88570bdd1b94309ad613395295f13449c3fMakoto Onuki /** 4560e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * Take the current flag indicating whether the loader's content had 4570e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * changed while it was stopped. If it had, true is returned and the 4580e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * flag is cleared. 4590e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn */ 4600e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn public boolean takeContentChanged() { 4610e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn boolean res = mContentChanged; 4620e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn mContentChanged = false; 463ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn mProcessingChange |= res; 4640e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn return res; 4650e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn } 466ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn 467ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn /** 468ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn * Commit that you have actually fully processed a content change that 469ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn * was returned by {@link #takeContentChanged}. This is for use with 470ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn * {@link #rollbackContentChanged()} to handle situations where a load 471ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn * is cancelled. Call this when you have completely processed a load 472ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn * without it being cancelled. 473ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn */ 474ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn public void commitContentChanged() { 475ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn mProcessingChange = false; 476ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn } 477ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn 478ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn /** 479ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn * Report that you have abandoned the processing of a content change that 480ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn * was returned by {@link #takeContentChanged()} and would like to rollback 481ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn * to the state where there is again a pending content change. This is 482ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn * to handle the case where a data load due to a content change has been 483ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn * canceled before its data was delivered back to the loader. 484ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn */ 485ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn public void rollbackContentChanged() { 486ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn if (mProcessingChange) { 4874be84bb10cf0bd998f33d9e5a7ca42cf8e072ad7Adam Powell onContentChanged(); 488ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn } 489ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn } 490ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn 4910e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn /** 4920e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * Called when {@link ForceLoadContentObserver} detects a change. The 4930e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * default implementation checks to see if the loader is currently started; 4940e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * if so, it simply calls {@link #forceLoad()}; otherwise, it sets a flag 4950e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * so that {@link #takeContentChanged()} returns true. 496ec37c88570bdd1b94309ad613395295f13449c3fMakoto Onuki * 497247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * <p>Must be called from the process's main thread. 498ec37c88570bdd1b94309ad613395295f13449c3fMakoto Onuki */ 499ec37c88570bdd1b94309ad613395295f13449c3fMakoto Onuki public void onContentChanged() { 5000e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn if (mStarted) { 5010e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn forceLoad(); 5020e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn } else { 5030e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn // This loader has been stopped, so we don't want to load 5040e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn // new data right now... but keep track of it changing to 5050e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn // refresh later if we start again. 5060e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn mContentChanged = true; 5070e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn } 508ec37c88570bdd1b94309ad613395295f13449c3fMakoto Onuki } 509a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 510a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn /** 511a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * For debugging, converts an instance of the Loader's data class to 512a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * a string that can be printed. Must handle a null data. 513a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn */ 514a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn public String dataToString(D data) { 515a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn StringBuilder sb = new StringBuilder(64); 516a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn DebugUtils.buildShortClassTag(data, sb); 517a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append("}"); 518a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn return sb.toString(); 519a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 520a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 521a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn @Override 522a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn public String toString() { 523a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn StringBuilder sb = new StringBuilder(64); 524a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn DebugUtils.buildShortClassTag(this, sb); 525a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append(" id="); 526a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append(mId); 527a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append("}"); 528a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn return sb.toString(); 529a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 530a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 531a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn /** 532a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * Print the Loader's state into the given stream. 533a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * 534a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * @param prefix Text to print at the front of each line. 535a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * @param fd The raw file descriptor that the dump is being sent to. 536a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * @param writer A PrintWriter to which the dump is to be set. 537a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * @param args Additional arguments to the dump request. 538a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn */ 539a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 540a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn writer.print(prefix); writer.print("mId="); writer.print(mId); 541a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn writer.print(" mListener="); writer.println(mListener); 542ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn if (mStarted || mContentChanged || mProcessingChange) { 543ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn writer.print(prefix); writer.print("mStarted="); writer.print(mStarted); 544ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn writer.print(" mContentChanged="); writer.print(mContentChanged); 545ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn writer.print(" mProcessingChange="); writer.println(mProcessingChange); 546ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn } 547ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn if (mAbandoned || mReset) { 548ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn writer.print(prefix); writer.print("mAbandoned="); writer.print(mAbandoned); 549ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn writer.print(" mReset="); writer.println(mReset); 550ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn } 551a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 5529911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton}