LoaderManager.java revision 260c3c77d9b340164e055f87002c64d78da6e836
1c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn/* 2c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn * Copyright (C) 2010 The Android Open Source Project 3c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn * 4c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License"); 5c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn * you may not use this file except in compliance with the License. 6c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn * You may obtain a copy of the License at 7c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn * 8c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn * http://www.apache.org/licenses/LICENSE-2.0 9c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn * 10c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn * Unless required by applicable law or agreed to in writing, software 11c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS, 12c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn * See the License for the specific language governing permissions and 14c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn * limitations under the License. 15c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn */ 16c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 17c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackbornpackage android.app; 18c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 19c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackbornimport android.content.Loader; 20c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackbornimport android.os.Bundle; 21a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackbornimport android.util.DebugUtils; 225e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackbornimport android.util.Log; 23c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackbornimport android.util.SparseArray; 24c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 2530d7189067524000c738c188c4ff91f84f474d25Dianne Hackbornimport java.io.FileDescriptor; 2630d7189067524000c738c188c4ff91f84f474d25Dianne Hackbornimport java.io.PrintWriter; 270e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackbornimport java.lang.reflect.Modifier; 2830d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn 29c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn/** 304911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * Interface associated with an {@link Activity} or {@link Fragment} for managing 31c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * one or more {@link android.content.Loader} instances associated with it. This 32c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * helps an application manage longer-running operations in conjunction with the 33c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * Activity or Fragment lifecycle; the most common use of this is with a 34c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * {@link android.content.CursorLoader}, however applications are free to write 35c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * their own loaders for loading other types of data. 36c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * 37c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * <p>As an example, here is the full implementation of a {@link Fragment} 38c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * that displays a {@link android.widget.ListView} containing the results of 39c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * a query against the contacts content provider. It uses a 40c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * {@link android.content.CursorLoader} to manage the query on the provider. 41c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * 42c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentListCursorLoader.java 43c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * fragment_cursor} 44c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn */ 45ab36acb39941ce981dddda9f9cf4d2d23a56fd26Dianne Hackbornpublic abstract class LoaderManager { 46c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn /** 47c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn * Callback interface for a client to interact with the manager. 48c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn */ 49c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn public interface LoaderCallbacks<D> { 504911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn /** 514911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * Instantiate and return a new Loader for the given ID. 524911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * 534911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * @param id The ID whose loader is to be created. 544911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * @param args Any arguments supplied by the caller. 554911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * @return Return a new Loader instance that is ready to start loading. 564911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn */ 57c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn public Loader<D> onCreateLoader(int id, Bundle args); 584911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn 594911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn /** 60fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn * Called when a previously created loader has finished its load. Note 61fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn * that normally an application is <em>not</em> allowed to commit fragment 62fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn * transactions while in this call, since it can happen after an 6348e7b458694acdf3a4fc58e62437f1dbc4f29d83Dianne Hackborn * activity's state is saved. See {@link FragmentManager#beginTransaction() 64fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn * FragmentManager.openTransaction()} for further discussion on this. 65fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn * 66c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * <p>This function is guaranteed to be called prior to the release of 67c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * the last data that was supplied for this Loader. At this point 68c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * you should remove all use of the old data (since it will be released 69c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * soon), but should not do your own release of the data since its Loader 70c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * owns it and will take care of that. The Loader will take care of 71c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * management of its data so you don't have to. In particular: 72c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * 73c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * <ul> 74c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * <li> <p>The Loader will monitor for changes to the data, and report 75c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * them to you through new calls here. You should not monitor the 76c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * data yourself. For example, if the data is a {@link android.database.Cursor} 77c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * and you place it in a {@link android.widget.CursorAdapter}, use 78c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * the {@link android.widget.CursorAdapter#CursorAdapter(android.content.Context, 79c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * android.database.Cursor, int)} constructor <em>without</em> passing 80c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * in either {@link android.widget.CursorAdapter#FLAG_AUTO_REQUERY} 81c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * or {@link android.widget.CursorAdapter#FLAG_REGISTER_CONTENT_OBSERVER} 82c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * (that is, use 0 for the flags argument). This prevents the CursorAdapter 83c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * from doing its own observing of the Cursor, which is not needed since 84c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * when a change happens you will get a new Cursor throw another call 85c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * here. 86c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * <li> The Loader will release the data once it knows the application 87c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * is no longer using it. For example, if the data is 88c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * a {@link android.database.Cursor} from a {@link android.content.CursorLoader}, 89c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * you should not call close() on it yourself. If the Cursor is being placed in a 90c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * {@link android.widget.CursorAdapter}, you should use the 91c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * {@link android.widget.CursorAdapter#swapCursor(android.database.Cursor)} 92c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * method so that the old Cursor is not closed. 93c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * </ul> 94c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * 954911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * @param loader The Loader that has finished. 964911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * @param data The data generated by the Loader. 974911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn */ 98c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn public void onLoadFinished(Loader<D> loader, D data); 99c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn 100c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn /** 101c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * Called when a previously created loader is being reset, and thus 102c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * making its data unavailable. The application should at this point 103c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * remove any references it has to the Loader's data. 104c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * 105c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * @param loader The Loader that is being reset. 106c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn */ 107c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn public void onLoaderReset(Loader<D> loader); 108c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 109c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 1104911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn /** 1114911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * Ensures a loader is initialized and active. If the loader doesn't 1124911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * already exist, one is created and (if the activity/fragment is currently 1134911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * started) starts the loader. Otherwise the last created 1144911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * loader is re-used. 1154911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * 1164911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * <p>In either case, the given callback is associated with the loader, and 1174911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * will be called as the loader state changes. If at the point of call 1184911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * the caller is in its started state, and the requested loader 1194911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * already exists and has generated its data, then 120c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * callback {@link LoaderCallbacks#onLoadFinished} will 1214911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * be called immediately (inside of this function), so you must be prepared 1224911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * for this to happen. 123c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * 124c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * @param id A unique identifier for this loader. Can be whatever you want. 125c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * Identifiers are scoped to a particular LoaderManager instance. 126c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * @param args Optional arguments to supply to the loader at construction. 127a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * If a loader already exists (a new one does not need to be created), this 128a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * parameter will be ignored and the last arguments continue to be used. 129c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * @param callback Interface the LoaderManager will call to report about 130c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * changes in the state of the loader. Required. 1314911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn */ 132ab36acb39941ce981dddda9f9cf4d2d23a56fd26Dianne Hackborn public abstract <D> Loader<D> initLoader(int id, Bundle args, 1334911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn LoaderManager.LoaderCallbacks<D> callback); 1344911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn 1354911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn /** 136c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * Starts a new or restarts an existing {@link android.content.Loader} in 137c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * this manager, registers the callbacks to it, 1384911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * and (if the activity/fragment is currently started) starts loading it. 1394911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * If a loader with the same id has previously been 1404911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * started it will automatically be destroyed when the new loader completes 1414911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * its work. The callback will be delivered before the old loader 1424911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * is destroyed. 143c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * 144c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * @param id A unique identifier for this loader. Can be whatever you want. 145c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * Identifiers are scoped to a particular LoaderManager instance. 146c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * @param args Optional arguments to supply to the loader at construction. 147c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * @param callback Interface the LoaderManager will call to report about 148c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * changes in the state of the loader. Required. 1494911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn */ 150ab36acb39941ce981dddda9f9cf4d2d23a56fd26Dianne Hackborn public abstract <D> Loader<D> restartLoader(int id, Bundle args, 1514911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn LoaderManager.LoaderCallbacks<D> callback); 1524911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn 1534911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn /** 154f73c75ca20fcaaee1b0eeaaf756252c33e3099c6Dianne Hackborn * Stops and removes the loader with the given ID. If this loader 155f73c75ca20fcaaee1b0eeaaf756252c33e3099c6Dianne Hackborn * had previously reported data to the client through 156f73c75ca20fcaaee1b0eeaaf756252c33e3099c6Dianne Hackborn * {@link LoaderCallbacks#onLoadFinished(Loader, Object)}, a call 157f73c75ca20fcaaee1b0eeaaf756252c33e3099c6Dianne Hackborn * will be made to {@link LoaderCallbacks#onLoaderReset(Loader)}. 1584911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn */ 159c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn public abstract void destroyLoader(int id); 160c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn 161c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn /** 1624911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * Return the Loader with the given id or null if no matching Loader 1634911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * is found. 1644911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn */ 165ab36acb39941ce981dddda9f9cf4d2d23a56fd26Dianne Hackborn public abstract <D> Loader<D> getLoader(int id); 16630d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn 16730d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn /** 16830d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn * Print the LoaderManager's state into the given stream. 16930d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn * 17030d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn * @param prefix Text to print at the front of each line. 17130d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn * @param fd The raw file descriptor that the dump is being sent to. 17230d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn * @param writer A PrintWriter to which the dump is to be set. 17330d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn * @param args Additional arguments to the dump request. 17430d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn */ 17530d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn public abstract void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args); 176a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 177a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn /** 178a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * Control whether the framework's internal loader manager debugging 179a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * logs are turned on. If enabled, you will see output in logcat as 180a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * the framework performs loader operations. 181a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn */ 182a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn public static void enableDebugLogging(boolean enabled) { 183a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn LoaderManagerImpl.DEBUG = enabled; 184a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 1854911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn} 1864911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn 187ab36acb39941ce981dddda9f9cf4d2d23a56fd26Dianne Hackbornclass LoaderManagerImpl extends LoaderManager { 188a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn static final String TAG = "LoaderManager"; 189ec541e1787b39605200584042fa1e144923eeb4fDianne Hackborn static boolean DEBUG = false; 1905e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 1915e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // These are the currently active loaders. A loader is here 1925e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // from the time its load is started until it has been explicitly 1935e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // stopped or restarted by the application. 1944911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn final SparseArray<LoaderInfo> mLoaders = new SparseArray<LoaderInfo>(); 1955e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 1965e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // These are previously run loaders. This list is maintained internally 1975e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // to avoid destroying a loader while an application is still using it. 1985e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // It allows an application to restart a loader, but continue using its 1995e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // previously run loader until the new loader's data is available. 2004911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn final SparseArray<LoaderInfo> mInactiveLoaders = new SparseArray<LoaderInfo>(); 2015e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 202fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn Activity mActivity; 2034911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn boolean mStarted; 2044911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn boolean mRetaining; 2054911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn boolean mRetainingStarted; 2066e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn 2076e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn boolean mCreatingLoader; 2084911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn 209c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn final class LoaderInfo implements Loader.OnLoadCompleteListener<Object> { 2102707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn final int mId; 2112707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn final Bundle mArgs; 2122707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn LoaderManager.LoaderCallbacks<Object> mCallbacks; 2132707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn Loader<Object> mLoader; 2146e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn boolean mHaveData; 2156e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn boolean mDeliveredData; 2162707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn Object mData; 2172707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn boolean mStarted; 2182707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn boolean mRetaining; 2192707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn boolean mRetainingStarted; 2202707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn boolean mDestroyed; 2212707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn boolean mListenerRegistered; 22230d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn 2236e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn LoaderInfo mPendingLoader; 2246e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn 2252707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn public LoaderInfo(int id, Bundle args, LoaderManager.LoaderCallbacks<Object> callbacks) { 2262707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mId = id; 2272707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mArgs = args; 2282707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mCallbacks = callbacks; 2292707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 2302707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 2312707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn void start() { 2322707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (mRetaining && mRetainingStarted) { 2332707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // Our owner is started, but we were being retained from a 2342707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // previous instance in the started state... so there is really 2352707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // nothing to do here, since the loaders are still started. 2362707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mStarted = true; 2372707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn return; 2382707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 2392707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 2404911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn if (mStarted) { 2414911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn // If loader already started, don't restart. 2424911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn return; 2434911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn } 2444911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn 2450e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn mStarted = true; 2460e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn 2475e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn if (DEBUG) Log.v(TAG, " Starting: " + this); 2482707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (mLoader == null && mCallbacks != null) { 2492707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mLoader = mCallbacks.onCreateLoader(mId, mArgs); 2502707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 2512707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (mLoader != null) { 2520e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn if (mLoader.getClass().isMemberClass() 2530e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn && !Modifier.isStatic(mLoader.getClass().getModifiers())) { 254a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn throw new IllegalArgumentException( 2550e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn "Object returned from onCreateLoader must not be a non-static inner member class: " 256a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn + mLoader); 257a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 2584911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn if (!mListenerRegistered) { 2594911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn mLoader.registerListener(mId, this); 2604911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn mListenerRegistered = true; 2614911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn } 2622707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mLoader.startLoading(); 2632707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 2642707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 2652707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 2662707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn void retain() { 2675e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn if (DEBUG) Log.v(TAG, " Retaining: " + this); 2682707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mRetaining = true; 2692707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mRetainingStarted = mStarted; 2702707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mStarted = false; 2712707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mCallbacks = null; 2722707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 2732707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 2742707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn void finishRetain() { 2752707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (mRetaining) { 2765e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn if (DEBUG) Log.v(TAG, " Finished Retaining: " + this); 2772707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mRetaining = false; 2782707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (mStarted != mRetainingStarted) { 2792707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (!mStarted) { 2802707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // This loader was retained in a started state, but 2812707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // at the end of retaining everything our owner is 2822707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // no longer started... so make it stop. 2832707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn stop(); 2842707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 2852707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 286c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } 287c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn 2886e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (mStarted && mHaveData) { 289c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn // This loader has retained its data, either completely across 290c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn // a configuration change or just whatever the last data set 291c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn // was after being restarted from a stop, and now at the point of 292c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn // finishing the retain we find we remain started, have 293c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn // our data, and the owner has a new callback... so 294c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn // let's deliver the data now. 295c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn callOnLoadFinished(mLoader, mData); 2962707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 2972707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 2982707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 2992707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn void stop() { 3005e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn if (DEBUG) Log.v(TAG, " Stopping: " + this); 3012707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mStarted = false; 302debb2e25b3ce2f0f5195a2895dd1882fc172d4d8Dianne Hackborn if (!mRetaining) { 303debb2e25b3ce2f0f5195a2895dd1882fc172d4d8Dianne Hackborn if (mLoader != null && mListenerRegistered) { 304debb2e25b3ce2f0f5195a2895dd1882fc172d4d8Dianne Hackborn // Let the loader know we're done with it 305debb2e25b3ce2f0f5195a2895dd1882fc172d4d8Dianne Hackborn mListenerRegistered = false; 306debb2e25b3ce2f0f5195a2895dd1882fc172d4d8Dianne Hackborn mLoader.unregisterListener(this); 307debb2e25b3ce2f0f5195a2895dd1882fc172d4d8Dianne Hackborn mLoader.stopLoading(); 308debb2e25b3ce2f0f5195a2895dd1882fc172d4d8Dianne Hackborn } 3092707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 3102707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 3112707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 3122707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn void destroy() { 3135e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn if (DEBUG) Log.v(TAG, " Destroying: " + this); 3142707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mDestroyed = true; 3156e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn boolean needReset = mDeliveredData; 3166e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn mDeliveredData = false; 3176e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (mCallbacks != null && mLoader != null && mHaveData && needReset) { 318a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, " Reseting: " + this); 319c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn String lastBecause = null; 320c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn if (mActivity != null) { 321c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn lastBecause = mActivity.mFragments.mNoTransactionsBecause; 322c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn mActivity.mFragments.mNoTransactionsBecause = "onLoaderReset"; 323c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } 324c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn try { 325c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn mCallbacks.onLoaderReset(mLoader); 326c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } finally { 327c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn if (mActivity != null) { 328c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn mActivity.mFragments.mNoTransactionsBecause = lastBecause; 329c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } 330c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } 331c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } 3322707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mCallbacks = null; 333c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn mData = null; 3346e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn mHaveData = false; 3352707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (mLoader != null) { 3362707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (mListenerRegistered) { 3372707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mListenerRegistered = false; 3382707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mLoader.unregisterListener(this); 3392707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 340c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn mLoader.reset(); 3412707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 3426e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (mPendingLoader != null) { 3436e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn mPendingLoader.destroy(); 3446e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn } 3452707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 346c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 347c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn @Override public void onLoadComplete(Loader<Object> loader, Object data) { 348a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "onLoadComplete: " + this); 3496e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn 3502707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (mDestroyed) { 351a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, " Ignoring load complete -- destroyed"); 3522707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn return; 3532707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 3546e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn 3556e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (mLoaders.get(mId) != this) { 3566e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn // This data is not coming from the current active loader. 3576e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn // We don't care about it. 3586e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (DEBUG) Log.v(TAG, " Ignoring load complete -- not active"); 3596e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn return; 3606e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn } 3616e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn 3626e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn LoaderInfo pending = mPendingLoader; 3636e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (pending != null) { 3646e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn // There is a new request pending and we were just 3656e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn // waiting for the old one to complete before starting 3666e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn // it. So now it is time, switch over to the new loader. 3676e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (DEBUG) Log.v(TAG, " Switching to pending loader: " + pending); 3686e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn mPendingLoader = null; 3696e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn mLoaders.put(mId, null); 3706e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn destroy(); 3716e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn installLoader(pending); 3726e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn return; 3736e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn } 3742707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 375c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn // Notify of the new data so the app can switch out the old data before 376c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn // we try to destroy it. 3776e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (mData != data || !mHaveData) { 3780e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn mData = data; 3796e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn mHaveData = true; 3800e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn if (mStarted) { 3810e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn callOnLoadFinished(loader, data); 3820e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn } 383c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } 384c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 385a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn //if (DEBUG) Log.v(TAG, " onLoadFinished returned: " + this); 3865e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 3875e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // We have now given the application the new loader with its 3885e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // loaded data, so it should have stopped using the previous 3895e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // loader. If there is a previous loader on the inactive list, 3905e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // clean it up. 3912707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn LoaderInfo info = mInactiveLoaders.get(mId); 3925e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn if (info != null && info != this) { 3936e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn info.mDeliveredData = false; 3945e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn info.destroy(); 3952707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mInactiveLoaders.remove(mId); 396c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 397c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 3985e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 399fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn void callOnLoadFinished(Loader<Object> loader, Object data) { 400fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn if (mCallbacks != null) { 401fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn String lastBecause = null; 402fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn if (mActivity != null) { 403fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn lastBecause = mActivity.mFragments.mNoTransactionsBecause; 404fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn mActivity.mFragments.mNoTransactionsBecause = "onLoadFinished"; 405fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } 406fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn try { 407a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, " onLoadFinished in " + loader + ": " 408a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn + loader.dataToString(data)); 409fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn mCallbacks.onLoadFinished(loader, data); 410fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } finally { 411fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn if (mActivity != null) { 412fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn mActivity.mFragments.mNoTransactionsBecause = lastBecause; 413fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } 414fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } 4156e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn mDeliveredData = true; 416fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } 417fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } 418fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn 4195e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn @Override 4205e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn public String toString() { 4215e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn StringBuilder sb = new StringBuilder(64); 4225e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn sb.append("LoaderInfo{"); 4235e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn sb.append(Integer.toHexString(System.identityHashCode(this))); 4245e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn sb.append(" #"); 4255e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn sb.append(mId); 426a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append(" : "); 427a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn DebugUtils.buildShortClassTag(mLoader, sb); 428a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append("}}"); 42930d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn return sb.toString(); 43030d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn } 43130d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn 43230d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 43330d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(prefix); writer.print("mId="); writer.print(mId); 43430d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(" mArgs="); writer.println(mArgs); 43530d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(prefix); writer.print("mCallbacks="); writer.println(mCallbacks); 43630d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(prefix); writer.print("mLoader="); writer.println(mLoader); 437a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (mLoader != null) { 438a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn mLoader.dump(prefix + " ", fd, writer, args); 439a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 4406e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (mHaveData || mDeliveredData) { 4416e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn writer.print(prefix); writer.print("mHaveData="); writer.print(mHaveData); 4426e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn writer.print(" mDeliveredData="); writer.println(mDeliveredData); 4436e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn writer.print(prefix); writer.print("mData="); writer.println(mData); 4446e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn } 44530d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(prefix); writer.print("mStarted="); writer.print(mStarted); 44630d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(" mRetaining="); writer.print(mRetaining); 447f73c75ca20fcaaee1b0eeaaf756252c33e3099c6Dianne Hackborn writer.print(" mDestroyed="); writer.println(mDestroyed); 4480e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn writer.print(prefix); writer.print("mListenerRegistered="); 4490e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn writer.println(mListenerRegistered); 4506e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (mPendingLoader != null) { 4516e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn writer.print(prefix); writer.println("Pending Loader "); 4526e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn writer.print(mPendingLoader); writer.println(":"); 4536e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn mPendingLoader.dump(prefix + " ", fd, writer, args); 4546e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn } 45530d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn } 456c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 457c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 458fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn LoaderManagerImpl(Activity activity, boolean started) { 459fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn mActivity = activity; 460c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn mStarted = started; 461c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 462c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 463fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn void updateActivity(Activity activity) { 464fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn mActivity = activity; 465fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } 466fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn 4672707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn private LoaderInfo createLoader(int id, Bundle args, 4682707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn LoaderManager.LoaderCallbacks<Object> callback) { 4692707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn LoaderInfo info = new LoaderInfo(id, args, (LoaderManager.LoaderCallbacks<Object>)callback); 4702707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn Loader<Object> loader = callback.onCreateLoader(id, args); 4712707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn info.mLoader = (Loader<Object>)loader; 4726e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn return info; 4736e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn } 4746e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn 4756e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn private LoaderInfo createAndInstallLoader(int id, Bundle args, 4766e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn LoaderManager.LoaderCallbacks<Object> callback) { 4776e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn try { 4786e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn mCreatingLoader = true; 4796e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn LoaderInfo info = createLoader(id, args, callback); 4806e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn installLoader(info); 4816e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn return info; 4826e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn } finally { 4836e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn mCreatingLoader = false; 4846e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn } 4856e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn } 4866e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn 4876e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn void installLoader(LoaderInfo info) { 4886e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn mLoaders.put(info.mId, info); 4892707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (mStarted) { 4904911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn // The activity will start all existing loaders in it's onStart(), 4914911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn // so only start them here if we're past that point of the activitiy's 4924911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn // life cycle 4934911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn info.start(); 4942707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 4952707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 4962707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 4976e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn /** 4986e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * Call to initialize a particular ID with a Loader. If this ID already 4996e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * has a Loader associated with it, it is left unchanged and any previous 5006e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * callbacks replaced with the newly provided ones. If there is not currently 5016e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * a Loader for the ID, a new one is created and started. 5026e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * 5036e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * <p>This function should generally be used when a component is initializing, 5046e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * to ensure that a Loader it relies on is created. This allows it to re-use 5056e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * an existing Loader's data if there already is one, so that for example 5066e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * when an {@link Activity} is re-created after a configuration change it 5076e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * does not need to re-create its loaders. 5086e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * 5096e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * <p>Note that in the case where an existing Loader is re-used, the 5106e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * <var>args</var> given here <em>will be ignored</em> because you will 5116e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * continue using the previous Loader. 5126e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * 5136e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * @param id A unique (to this LoaderManager instance) identifier under 5146e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * which to manage the new Loader. 5156e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * @param args Optional arguments that will be propagated to 5166e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * {@link LoaderCallbacks#onCreateLoader(int, Bundle) LoaderCallbacks.onCreateLoader()}. 5176e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * @param callback Interface implementing management of this Loader. Required. 5186e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * Its onCreateLoader() method will be called while inside of the function to 5196e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * instantiate the Loader object. 5206e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn */ 5212707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn @SuppressWarnings("unchecked") 5222707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn public <D> Loader<D> initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) { 5236e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (mCreatingLoader) { 5246e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn throw new IllegalStateException("Called while creating a loader"); 5256e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn } 5266e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn 5272707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn LoaderInfo info = mLoaders.get(id); 5282707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 529a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "initLoader in " + this + ": args=" + args); 5305e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 5312707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (info == null) { 5322707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // Loader doesn't already exist; create. 5336e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn info = createAndInstallLoader(id, args, (LoaderManager.LoaderCallbacks<Object>)callback); 534a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, " Created new loader " + info); 5352707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } else { 536a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, " Re-using existing loader " + info); 5372707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn info.mCallbacks = (LoaderManager.LoaderCallbacks<Object>)callback; 5382707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 5392707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 5406e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (info.mHaveData && mStarted) { 5412707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // If the loader has already generated its data, report it now. 542fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn info.callOnLoadFinished(info.mLoader, info.mData); 5432707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 5442707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 5452707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn return (Loader<D>)info.mLoader; 5462707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 5472707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 5486e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn /** 5496e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * Call to re-create the Loader associated with a particular ID. If there 5506e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * is currently a Loader associated with this ID, it will be 5516e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * canceled/stopped/destroyed as appropriate. A new Loader with the given 5526e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * arguments will be created and its data delivered to you once available. 5536e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * 5546e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * <p>This function does some throttling of Loaders. If too many Loaders 5556e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * have been created for the given ID but not yet generated their data, 5566e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * new calls to this function will create and return a new Loader but not 5576e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * actually start it until some previous loaders have completed. 5586e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * 5596e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * <p>After calling this function, any previous Loaders associated with 5606e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * this ID will be considered invalid, and you will receive no further 5616e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * data updates from them. 5626e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * 5636e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * @param id A unique (to this LoaderManager instance) identifier under 5646e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * which to manage the new Loader. 5656e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * @param args Optional arguments that will be propagated to 5666e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * {@link LoaderCallbacks#onCreateLoader(int, Bundle) LoaderCallbacks.onCreateLoader()}. 5676e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * @param callback Interface implementing management of this Loader. Required. 5686e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * Its onCreateLoader() method will be called while inside of the function to 5696e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * instantiate the Loader object. 5706e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn */ 571c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn @SuppressWarnings("unchecked") 5722707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn public <D> Loader<D> restartLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) { 5736e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (mCreatingLoader) { 5746e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn throw new IllegalStateException("Called while creating a loader"); 5756e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn } 5766e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn 577c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn LoaderInfo info = mLoaders.get(id); 578a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "restartLoader in " + this + ": args=" + args); 579c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn if (info != null) { 5805e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn LoaderInfo inactive = mInactiveLoaders.get(id); 5815e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn if (inactive != null) { 5826e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (info.mHaveData) { 5835e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // This loader now has data... we are probably being 5845e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // called from within onLoadComplete, where we haven't 5855e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // yet destroyed the last inactive loader. So just do 5865e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // that now. 587a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, " Removing last inactive loader: " + info); 5886e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn inactive.mDeliveredData = false; 5895e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn inactive.destroy(); 590260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn info.mLoader.abandon(); 5915e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn mInactiveLoaders.put(id, info); 5925e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn } else { 5935e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // We already have an inactive loader for this ID that we are 5946e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn // waiting for! What to do, what to do... 5956e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (!info.mStarted) { 5966e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn // The current Loader has not been started... we thus 5976e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn // have no reason to keep it around, so bam, slam, 5986e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn // thank-you-ma'am. 5996e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (DEBUG) Log.v(TAG, " Current loader is stopped; replacing"); 6006e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn mLoaders.put(id, null); 6016e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn info.destroy(); 6026e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn } else { 6036e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn // Now we have three active loaders... we'll queue 6046e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn // up this request to be processed once one of the other loaders 6056e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn // finishes. 6066e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (info.mPendingLoader != null) { 6076e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (DEBUG) Log.v(TAG, " Removing pending loader: " + info.mPendingLoader); 6086e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn info.mPendingLoader.destroy(); 6096e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn info.mPendingLoader = null; 6106e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn } 6116e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (DEBUG) Log.v(TAG, " Enqueuing as new pending loader"); 6126e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn info.mPendingLoader = createLoader(id, args, 6136e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn (LoaderManager.LoaderCallbacks<Object>)callback); 6146e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn return (Loader<D>)info.mPendingLoader.mLoader; 6156e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn } 6165e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn } 6172707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } else { 6182707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // Keep track of the previous instance of this loader so we can destroy 6192707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // it when the new one completes. 620a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, " Making last loader inactive: " + info); 621260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn info.mLoader.abandon(); 6222707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mInactiveLoaders.put(id, info); 6232707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 624c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 625c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 6266e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn info = createAndInstallLoader(id, args, (LoaderManager.LoaderCallbacks<Object>)callback); 6272707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn return (Loader<D>)info.mLoader; 628c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 629c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 6306e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn /** 6316e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * Rip down, tear apart, shred to pieces a current Loader ID. After returning 6326e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * from this function, any Loader objects associated with this ID are 6336e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * destroyed. Any data associated with them is destroyed. You better not 6346e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * be using it when you do this. 6356e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * @param id Identifier of the Loader to be destroyed. 6366e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn */ 637c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn public void destroyLoader(int id) { 6386e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (mCreatingLoader) { 6396e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn throw new IllegalStateException("Called while creating a loader"); 6406e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn } 6416e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn 642a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "destroyLoader in " + this + " of " + id); 6432707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn int idx = mLoaders.indexOfKey(id); 6442707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (idx >= 0) { 6452707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn LoaderInfo info = mLoaders.valueAt(idx); 6462707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mLoaders.removeAt(idx); 6474911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn info.destroy(); 648c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 649f73c75ca20fcaaee1b0eeaaf756252c33e3099c6Dianne Hackborn idx = mInactiveLoaders.indexOfKey(id); 650f73c75ca20fcaaee1b0eeaaf756252c33e3099c6Dianne Hackborn if (idx >= 0) { 651f73c75ca20fcaaee1b0eeaaf756252c33e3099c6Dianne Hackborn LoaderInfo info = mInactiveLoaders.valueAt(idx); 652f73c75ca20fcaaee1b0eeaaf756252c33e3099c6Dianne Hackborn mInactiveLoaders.removeAt(idx); 653f73c75ca20fcaaee1b0eeaaf756252c33e3099c6Dianne Hackborn info.destroy(); 654f73c75ca20fcaaee1b0eeaaf756252c33e3099c6Dianne Hackborn } 655c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 656c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 6576e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn /** 6586e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * Return the most recent Loader object associated with the 6596e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn * given ID. 6606e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn */ 661c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn @SuppressWarnings("unchecked") 662c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn public <D> Loader<D> getLoader(int id) { 6636e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (mCreatingLoader) { 6646e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn throw new IllegalStateException("Called while creating a loader"); 6656e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn } 6666e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn 667c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn LoaderInfo loaderInfo = mLoaders.get(id); 668c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn if (loaderInfo != null) { 6696e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn if (loaderInfo.mPendingLoader != null) { 6706e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn return (Loader<D>)loaderInfo.mPendingLoader.mLoader; 6716e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn } 6726e1bf6a3054674281bafd270165c99cb2423666dDianne Hackborn return (Loader<D>)loaderInfo.mLoader; 673c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 674c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn return null; 675c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 676c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 677c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn void doStart() { 678a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "Starting in " + this); 679fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn if (mStarted) { 680fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn RuntimeException e = new RuntimeException("here"); 681fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn e.fillInStackTrace(); 682fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn Log.w(TAG, "Called doStart when already started: " + this, e); 683fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn return; 684fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } 685fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn 686c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn mStarted = true; 687c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn 688c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn // Call out to sub classes so they can start their loaders 689c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn // Let the existing loaders know that we want to be notified when a load is complete 690c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn for (int i = mLoaders.size()-1; i >= 0; i--) { 6912707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mLoaders.valueAt(i).start(); 692c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 693c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 694c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 695c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn void doStop() { 696a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "Stopping in " + this); 697fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn if (!mStarted) { 698fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn RuntimeException e = new RuntimeException("here"); 699fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn e.fillInStackTrace(); 700fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn Log.w(TAG, "Called doStop when not started: " + this, e); 701fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn return; 702fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } 7035e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 704c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn for (int i = mLoaders.size()-1; i >= 0; i--) { 7052707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mLoaders.valueAt(i).stop(); 706c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 707c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn mStarted = false; 708c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 709c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 7102707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn void doRetain() { 711a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "Retaining in " + this); 712fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn if (!mStarted) { 713fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn RuntimeException e = new RuntimeException("here"); 714fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn e.fillInStackTrace(); 715fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn Log.w(TAG, "Called doRetain when not started: " + this, e); 716fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn return; 717fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } 7185e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 7192707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mRetaining = true; 7202707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mStarted = false; 7212707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn for (int i = mLoaders.size()-1; i >= 0; i--) { 7222707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mLoaders.valueAt(i).retain(); 7232707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 7242707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 7252707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 7262707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn void finishRetain() { 727a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (mRetaining) { 728a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "Finished Retaining in " + this); 7295e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 730a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn mRetaining = false; 731a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn for (int i = mLoaders.size()-1; i >= 0; i--) { 732a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn mLoaders.valueAt(i).finishRetain(); 733a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 7342707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 7352707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 7362707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 737c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn void doDestroy() { 7382707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (!mRetaining) { 739a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "Destroying Active in " + this); 740c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn for (int i = mLoaders.size()-1; i >= 0; i--) { 7412707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mLoaders.valueAt(i).destroy(); 742c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 743c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 7442707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 745a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "Destroying Inactive in " + this); 7462707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn for (int i = mInactiveLoaders.size()-1; i >= 0; i--) { 7472707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mInactiveLoaders.valueAt(i).destroy(); 7482707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 7492707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mInactiveLoaders.clear(); 750c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 75130d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn 75230d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn @Override 753a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn public String toString() { 754a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn StringBuilder sb = new StringBuilder(128); 755a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append("LoaderManager{"); 756a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append(Integer.toHexString(System.identityHashCode(this))); 757a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append(" in "); 758a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn DebugUtils.buildShortClassTag(mActivity, sb); 759a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append("}}"); 760a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn return sb.toString(); 761a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 762a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 763a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn @Override 76430d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 76530d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn if (mLoaders.size() > 0) { 76630d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(prefix); writer.println("Active Loaders:"); 76730d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn String innerPrefix = prefix + " "; 76830d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn for (int i=0; i < mLoaders.size(); i++) { 76930d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn LoaderInfo li = mLoaders.valueAt(i); 77030d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(prefix); writer.print(" #"); writer.print(mLoaders.keyAt(i)); 771a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn writer.print(": "); writer.println(li.toString()); 77230d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn li.dump(innerPrefix, fd, writer, args); 77330d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn } 77430d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn } 77530d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn if (mInactiveLoaders.size() > 0) { 77630d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(prefix); writer.println("Inactive Loaders:"); 77730d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn String innerPrefix = prefix + " "; 77830d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn for (int i=0; i < mInactiveLoaders.size(); i++) { 77930d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn LoaderInfo li = mInactiveLoaders.valueAt(i); 78030d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(prefix); writer.print(" #"); writer.print(mInactiveLoaders.keyAt(i)); 781a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn writer.print(": "); writer.println(li.toString()); 78230d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn li.dump(innerPrefix, fd, writer, args); 78330d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn } 78430d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn } 78530d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn } 786c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn} 787