Loader.java revision 2c84cfc001fb92a71811bf7384b7f865ff31ff9d
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/** 279911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * An abstract 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; 559911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton Context mContext; 56a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn boolean mStarted = false; 57260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn boolean mAbandoned = false; 58a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn boolean mReset = true; 590e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn boolean mContentChanged = false; 609911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 619911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public final class ForceLoadContentObserver extends ContentObserver { 629911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public ForceLoadContentObserver() { 639911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton super(new Handler()); 649911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 659911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 669911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton @Override 679911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public boolean deliverSelfNotifications() { 689911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton return true; 699911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 709911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 719911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton @Override 729911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public void onChange(boolean selfChange) { 73ec37c88570bdd1b94309ad613395295f13449c3fMakoto Onuki onContentChanged(); 749911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 759911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 769911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 779911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public interface OnLoadCompleteListener<D> { 789911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 799911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * Called on the thread that created the Loader when the load is complete. 809911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * 819911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * @param loader the loader that completed the load 829911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * @param data the result of the load 839911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 849911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public void onLoadComplete(Loader<D> loader, D data); 859911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 869911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 879911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 889567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * Stores away the application context associated with context. 899567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * Since Loaders can be used across multiple activities it's dangerous to 909567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * store the context directly; always use {@link #getContext()} to retrieve 919567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * the Loader's Context, don't use the constructor argument directly. 929567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * The Context returned by {@link #getContext} is safe to use across 939567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * Activity instances. 949911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * 959911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * @param context used to retrieve the application context. 969911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 979911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public Loader(Context context) { 989911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton mContext = context.getApplicationContext(); 999911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1009911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 1019911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 1029911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * Sends the result of the load to the registered listener. Should only be called by subclasses. 1039911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * 104247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * Must be called from the process's main thread. 1059911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * 1069911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * @param data the result of the load 1079911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 1089911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public void deliverResult(D data) { 1099911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton if (mListener != null) { 1109911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton mListener.onLoadComplete(this, data); 1119911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1129911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1139911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 1149911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 1159911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * @return an application context retrieved from the Context passed to the constructor. 1169911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 1179911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public Context getContext() { 1189911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton return mContext; 1199911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1209911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 1219911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 1229911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * @return the ID of this loader 1239911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 1249911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public int getId() { 1259911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton return mId; 1269911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1279911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 1289911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 129247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * Registers a class that will receive callbacks when a load is complete. 130247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * The callback will be called on the process's main thread so it's safe to 131247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * pass the results to widgets. 132ec37c88570bdd1b94309ad613395295f13449c3fMakoto Onuki * 133247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * <p>Must be called from the process's main thread. 1349911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 1359911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public void registerListener(int id, OnLoadCompleteListener<D> listener) { 1369911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton if (mListener != null) { 1379911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton throw new IllegalStateException("There is already a listener registered"); 1389911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1399911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton mListener = listener; 1409911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton mId = id; 1419911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1429911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 1439911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 144247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * Remove a listener that was previously added with {@link #registerListener}. 145247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * 146247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * Must be called from the process's main thread. 1479911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 1489911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton public void unregisterListener(OnLoadCompleteListener<D> listener) { 1499911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton if (mListener == null) { 1509911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton throw new IllegalStateException("No listener register"); 1519911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1529911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton if (mListener != listener) { 1539911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton throw new IllegalArgumentException("Attempting to unregister the wrong listener"); 1549911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1559911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton mListener = null; 1569911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton } 1579911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 1589911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 159a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * Return whether this load has been started. That is, its {@link #startLoading()} 160a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * has been called and no calls to {@link #stopLoading()} or 161a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * {@link #reset()} have yet been made. 162a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn */ 163a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn public boolean isStarted() { 164a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn return mStarted; 165a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 166a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 167a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn /** 168260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * Return whether this loader has been abandoned. In this state, the 169260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * loader <em>must not</em> report any new data, and <em>must</em> keep 170260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * its last reported data valid until it is finally reset. 171260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn */ 172260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn public boolean isAbandoned() { 173260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn return mAbandoned; 174260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn } 175260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn 176260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn /** 177a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * Return whether this load has been reset. That is, either the loader 178a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * has not yet been started for the first time, or its {@link #reset()} 179a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * has been called. 180a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn */ 181a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn public boolean isReset() { 182a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn return mReset; 183a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 184a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 185a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn /** 1862c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * This function will normally be called for you automatically by 1872c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * {@link android.app.LoaderManager} when the associated fragment/activity 1882c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * is being started. When using a Loader with {@link android.app.LoaderManager}, 1892c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * you <em>must not</em> call this method yourself, or you will conflict 1902c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * with its management of the Loader. 1912c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * 192247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * Starts an asynchronous load of the Loader's data. When the result 193247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * is ready the callbacks will be called on the process's main thread. 194247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * If a previous load has been completed and is still valid 195247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * the result may be passed to the callbacks immediately. 196247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * The loader will monitor the source of 197247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * the data set and may deliver future callbacks if the source changes. 198247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * Calling {@link #stopLoading} will stop the delivery of callbacks. 1999911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * 200a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * <p>This updates the Loader's internal state so that 201a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * {@link #isStarted()} and {@link #isReset()} will return the correct 202a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * values, and then calls the implementation's {@link #onStartLoading()}. 203a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * 204247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * <p>Must be called from the process's main thread. 205a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn */ 2060e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn public final void startLoading() { 207a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn mStarted = true; 208a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn mReset = false; 209260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn mAbandoned = false; 210a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn onStartLoading(); 211a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 212a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 213a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn /** 214a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * Subclasses must implement this to take care of loading their data, 215a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * as per {@link #startLoading()}. This is not called by clients directly, 216a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * but as a result of a call to {@link #startLoading()}. 2179911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 218a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn protected void onStartLoading() { 219a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 2209911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 2219911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 2229911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * Force an asynchronous load. Unlike {@link #startLoading()} this will ignore a previously 223a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * loaded data set and load a new one. This simply calls through to the 2240e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * implementation's {@link #onForceLoad()}. You generally should only call this 2250e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * when the loader is started -- that is, {@link #isStarted()} returns true. 226a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * 227247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * <p>Must be called from the process's main thread. 2289911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 229247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn public void forceLoad() { 230a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn onForceLoad(); 231a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 2329911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 2339911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 234a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * Subclasses must implement this to take care of requests to {@link #forceLoad()}. 235247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * This will always be called from the process's main thread. 236a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn */ 237a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn protected void onForceLoad() { 238a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 239a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 240a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn /** 2412c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * This function will normally be called for you automatically by 2422c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * {@link android.app.LoaderManager} when the associated fragment/activity 2432c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * is being stopped. When using a Loader with {@link android.app.LoaderManager}, 2442c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * you <em>must not</em> call this method yourself, or you will conflict 2452c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * with its management of the Loader. 2462c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * 2472c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * <p>Stops delivery of updates until the next time {@link #startLoading()} is called. 2480e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * Implementations should <em>not</em> invalidate their data at this point -- 2490e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * clients are still free to use the last data the loader reported. They will, 2500e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * however, typically stop reporting new data if the data changes; they can 2510e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * still monitor for changes, but must not report them to the client until and 2520e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * if {@link #startLoading()} is later called. 2539911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * 254a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * <p>This updates the Loader's internal state so that 255a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * {@link #isStarted()} will return the correct 256a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * value, and then calls the implementation's {@link #onStopLoading()}. 257a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * 258247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * <p>Must be called from the process's main thread. 2599911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 260247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn public void stopLoading() { 261a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn mStarted = false; 262a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn onStopLoading(); 263a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 264a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 265a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn /** 266a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * Subclasses must implement this to take care of stopping their loader, 267a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * as per {@link #stopLoading()}. This is not called by clients directly, 268a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * but as a result of a call to {@link #stopLoading()}. 269247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * This will always be called from the process's main thread. 270a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn */ 271a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn protected void onStopLoading() { 272a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 2739911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton 2749911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton /** 2752c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * This function will normally be called for you automatically by 2762c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * {@link android.app.LoaderManager} when restarting a Loader. When using 2772c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * a Loader with {@link android.app.LoaderManager}, 2782c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * you <em>must not</em> call this method yourself, or you will conflict 2792c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * with its management of the Loader. 2802c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * 281260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * Tell the Loader that it is being abandoned. This is called prior 282260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * to {@link #reset} to have it retain its current data but not report 283260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * any new data. 284260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn */ 285260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn public void abandon() { 286260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn mAbandoned = true; 287260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn onAbandon(); 288260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn } 289260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn 290260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn /** 291260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * Subclasses implement this to take care of being abandoned. This is 292260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * an optional intermediate state prior to {@link #onReset()} -- it means that 293260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * the client is no longer interested in any new data from the loader, 294260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * so the loader must not report any further updates. However, the 295260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * loader <em>must</em> keep its last reported data valid until the final 296260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * {@link #onReset()} happens. You can retrieve the current abandoned 297260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn * state with {@link #isAbandoned}. 298260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn */ 299260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn protected void onAbandon() { 300260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn } 301260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn 302260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn /** 3032c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * This function will normally be called for you automatically by 3042c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * {@link android.app.LoaderManager} when destroying a Loader. When using 3052c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * a Loader with {@link android.app.LoaderManager}, 3062c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * you <em>must not</em> call this method yourself, or you will conflict 3072c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * with its management of the Loader. 3082c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn * 309c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * Resets the state of the Loader. The Loader should at this point free 310c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * all of its resources, since it may never be called again; however, its 311c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * {@link #startLoading()} may later be called at which point it must be 312c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * able to start running again. 3139911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * 314a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * <p>This updates the Loader's internal state so that 315a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * {@link #isStarted()} and {@link #isReset()} will return the correct 316a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * values, and then calls the implementation's {@link #onReset()}. 317a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * 318247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * <p>Must be called from the process's main thread. 3199911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */ 320247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn public void reset() { 321a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn onReset(); 322a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn mReset = true; 323a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn mStarted = false; 324260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn mAbandoned = false; 3250e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn mContentChanged = false; 326c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } 327c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn 328c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn /** 329a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * Subclasses must implement this to take care of resetting their loader, 330a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * as per {@link #reset()}. This is not called by clients directly, 331a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * but as a result of a call to {@link #reset()}. 332247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * This will always be called from the process's main thread. 333c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn */ 334a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn protected void onReset() { 335c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } 336ec37c88570bdd1b94309ad613395295f13449c3fMakoto Onuki 337ec37c88570bdd1b94309ad613395295f13449c3fMakoto Onuki /** 3380e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * Take the current flag indicating whether the loader's content had 3390e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * changed while it was stopped. If it had, true is returned and the 3400e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * flag is cleared. 3410e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn */ 3420e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn public boolean takeContentChanged() { 3430e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn boolean res = mContentChanged; 3440e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn mContentChanged = false; 3450e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn return res; 3460e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn } 3470e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn 3480e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn /** 3490e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * Called when {@link ForceLoadContentObserver} detects a change. The 3500e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * default implementation checks to see if the loader is currently started; 3510e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * if so, it simply calls {@link #forceLoad()}; otherwise, it sets a flag 3520e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn * so that {@link #takeContentChanged()} returns true. 353ec37c88570bdd1b94309ad613395295f13449c3fMakoto Onuki * 354247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn * <p>Must be called from the process's main thread. 355ec37c88570bdd1b94309ad613395295f13449c3fMakoto Onuki */ 356ec37c88570bdd1b94309ad613395295f13449c3fMakoto Onuki public void onContentChanged() { 3570e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn if (mStarted) { 3580e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn forceLoad(); 3590e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn } else { 3600e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn // This loader has been stopped, so we don't want to load 3610e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn // new data right now... but keep track of it changing to 3620e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn // refresh later if we start again. 3630e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn mContentChanged = true; 3640e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn } 365ec37c88570bdd1b94309ad613395295f13449c3fMakoto Onuki } 366a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 367a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn /** 368a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * For debugging, converts an instance of the Loader's data class to 369a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * a string that can be printed. Must handle a null data. 370a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn */ 371a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn public String dataToString(D data) { 372a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn StringBuilder sb = new StringBuilder(64); 373a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn DebugUtils.buildShortClassTag(data, sb); 374a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append("}"); 375a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn return sb.toString(); 376a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 377a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 378a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn @Override 379a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn public String toString() { 380a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn StringBuilder sb = new StringBuilder(64); 381a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn DebugUtils.buildShortClassTag(this, sb); 382a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append(" id="); 383a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append(mId); 384a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append("}"); 385a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn return sb.toString(); 386a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 387a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 388a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn /** 389a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * Print the Loader's state into the given stream. 390a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * 391a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * @param prefix Text to print at the front of each line. 392a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * @param fd The raw file descriptor that the dump is being sent to. 393a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * @param writer A PrintWriter to which the dump is to be set. 394a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * @param args Additional arguments to the dump request. 395a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn */ 396a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 397a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn writer.print(prefix); writer.print("mId="); writer.print(mId); 398a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn writer.print(" mListener="); writer.println(mListener); 399a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn writer.print(prefix); writer.print("mStarted="); writer.print(mStarted); 4000e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn writer.print(" mContentChanged="); writer.print(mContentChanged); 401260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn writer.print(" mAbandoned="); writer.print(mAbandoned); 402a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn writer.print(" mReset="); writer.println(mReset); 403a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 4049911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton}