LoaderManager.java revision 0e3b8f421dfcc5363f234eb1b76479cb2fb2e8ee
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 63fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn * activity's state is saved. See {@link FragmentManager#openTransaction() 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 /** 162c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn * @deprecated Renamed to {@link #destroyLoader}. 163c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn */ 164c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn @Deprecated 165c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn public void stopLoader(int id) { 166c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn destroyLoader(id); 167c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } 1684911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn 1694911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn /** 1704911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * Return the Loader with the given id or null if no matching Loader 1714911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn * is found. 1724911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn */ 173ab36acb39941ce981dddda9f9cf4d2d23a56fd26Dianne Hackborn public abstract <D> Loader<D> getLoader(int id); 17430d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn 17530d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn /** 17630d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn * Print the LoaderManager's state into the given stream. 17730d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn * 17830d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn * @param prefix Text to print at the front of each line. 17930d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn * @param fd The raw file descriptor that the dump is being sent to. 18030d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn * @param writer A PrintWriter to which the dump is to be set. 18130d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn * @param args Additional arguments to the dump request. 18230d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn */ 18330d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn public abstract void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args); 184a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 185a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn /** 186a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * Control whether the framework's internal loader manager debugging 187a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * logs are turned on. If enabled, you will see output in logcat as 188a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn * the framework performs loader operations. 189a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn */ 190a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn public static void enableDebugLogging(boolean enabled) { 191a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn LoaderManagerImpl.DEBUG = enabled; 192a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 1934911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn} 1944911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn 195ab36acb39941ce981dddda9f9cf4d2d23a56fd26Dianne Hackbornclass LoaderManagerImpl extends LoaderManager { 196a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn static final String TAG = "LoaderManager"; 197a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn static boolean DEBUG = true; 1985e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 1995e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // These are the currently active loaders. A loader is here 2005e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // from the time its load is started until it has been explicitly 2015e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // stopped or restarted by the application. 2024911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn final SparseArray<LoaderInfo> mLoaders = new SparseArray<LoaderInfo>(); 2035e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 2045e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // These are previously run loaders. This list is maintained internally 2055e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // to avoid destroying a loader while an application is still using it. 2065e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // It allows an application to restart a loader, but continue using its 2075e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // previously run loader until the new loader's data is available. 2084911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn final SparseArray<LoaderInfo> mInactiveLoaders = new SparseArray<LoaderInfo>(); 2095e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 210fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn Activity mActivity; 2114911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn boolean mStarted; 2124911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn boolean mRetaining; 2134911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn boolean mRetainingStarted; 2144911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn 215c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn final class LoaderInfo implements Loader.OnLoadCompleteListener<Object> { 2162707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn final int mId; 2172707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn final Bundle mArgs; 2182707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn LoaderManager.LoaderCallbacks<Object> mCallbacks; 2192707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn Loader<Object> mLoader; 2202707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn Object mData; 2210e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn Object mDeliveredData; 2222707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn boolean mStarted; 2232707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn boolean mRetaining; 2242707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn boolean mRetainingStarted; 2252707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn boolean mDestroyed; 2262707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn boolean mListenerRegistered; 22730d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn 2282707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn public LoaderInfo(int id, Bundle args, LoaderManager.LoaderCallbacks<Object> callbacks) { 2292707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mId = id; 2302707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mArgs = args; 2312707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mCallbacks = callbacks; 2322707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 2332707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 2342707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn void start() { 2352707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (mRetaining && mRetainingStarted) { 2362707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // Our owner is started, but we were being retained from a 2372707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // previous instance in the started state... so there is really 2382707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // nothing to do here, since the loaders are still started. 2392707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mStarted = true; 2402707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn return; 2412707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 2422707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 2434911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn if (mStarted) { 2444911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn // If loader already started, don't restart. 2454911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn return; 2464911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn } 2474911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn 2480e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn mStarted = true; 2490e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn 2505e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn if (DEBUG) Log.v(TAG, " Starting: " + this); 2512707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (mLoader == null && mCallbacks != null) { 2522707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mLoader = mCallbacks.onCreateLoader(mId, mArgs); 2532707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 2542707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (mLoader != null) { 2550e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn if (mLoader.getClass().isMemberClass() 2560e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn && !Modifier.isStatic(mLoader.getClass().getModifiers())) { 257a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn throw new IllegalArgumentException( 2580e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn "Object returned from onCreateLoader must not be a non-static inner member class: " 259a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn + mLoader); 260a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 2614911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn if (!mListenerRegistered) { 2624911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn mLoader.registerListener(mId, this); 2634911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn mListenerRegistered = true; 2644911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn } 2652707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mLoader.startLoading(); 2662707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 2672707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 2682707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 2692707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn void retain() { 2705e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn if (DEBUG) Log.v(TAG, " Retaining: " + this); 2712707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mRetaining = true; 2722707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mRetainingStarted = mStarted; 2732707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mStarted = false; 2742707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mCallbacks = null; 2752707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 2762707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 2772707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn void finishRetain() { 2782707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (mRetaining) { 2795e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn if (DEBUG) Log.v(TAG, " Finished Retaining: " + this); 2802707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mRetaining = false; 2812707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (mStarted != mRetainingStarted) { 2822707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (!mStarted) { 2832707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // This loader was retained in a started state, but 2842707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // at the end of retaining everything our owner is 2852707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // no longer started... so make it stop. 2862707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn stop(); 2872707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 2882707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 289c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } 290c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn 291c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn if (mStarted && mData != null) { 292c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn // This loader has retained its data, either completely across 293c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn // a configuration change or just whatever the last data set 294c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn // was after being restarted from a stop, and now at the point of 295c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn // finishing the retain we find we remain started, have 296c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn // our data, and the owner has a new callback... so 297c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn // let's deliver the data now. 298c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn callOnLoadFinished(mLoader, mData); 2992707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 3002707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 3012707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 3022707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn void stop() { 3035e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn if (DEBUG) Log.v(TAG, " Stopping: " + this); 3042707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mStarted = false; 305debb2e25b3ce2f0f5195a2895dd1882fc172d4d8Dianne Hackborn if (!mRetaining) { 306debb2e25b3ce2f0f5195a2895dd1882fc172d4d8Dianne Hackborn if (mLoader != null && mListenerRegistered) { 307debb2e25b3ce2f0f5195a2895dd1882fc172d4d8Dianne Hackborn // Let the loader know we're done with it 308debb2e25b3ce2f0f5195a2895dd1882fc172d4d8Dianne Hackborn mListenerRegistered = false; 309debb2e25b3ce2f0f5195a2895dd1882fc172d4d8Dianne Hackborn mLoader.unregisterListener(this); 310debb2e25b3ce2f0f5195a2895dd1882fc172d4d8Dianne Hackborn mLoader.stopLoading(); 311debb2e25b3ce2f0f5195a2895dd1882fc172d4d8Dianne Hackborn } 3122707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 3132707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 3142707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 3152707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn void destroy() { 3165e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn if (DEBUG) Log.v(TAG, " Destroying: " + this); 3172707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mDestroyed = true; 3180e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn boolean needReset = mDeliveredData != null; 3190e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn mDeliveredData = null; 320a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (mCallbacks != null && mLoader != null && mData != null && needReset) { 321a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, " Reseting: " + this); 322c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn String lastBecause = null; 323c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn if (mActivity != null) { 324c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn lastBecause = mActivity.mFragments.mNoTransactionsBecause; 325c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn mActivity.mFragments.mNoTransactionsBecause = "onLoaderReset"; 326c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } 327c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn try { 328c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn mCallbacks.onLoaderReset(mLoader); 329c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } finally { 330c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn if (mActivity != null) { 331c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn mActivity.mFragments.mNoTransactionsBecause = lastBecause; 332c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } 333c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } 334c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } 3352707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mCallbacks = null; 336c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn mData = null; 3372707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (mLoader != null) { 3382707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (mListenerRegistered) { 3392707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mListenerRegistered = false; 3402707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mLoader.unregisterListener(this); 3412707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 342c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn mLoader.reset(); 3432707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 3442707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 345c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 346c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn @Override public void onLoadComplete(Loader<Object> loader, Object data) { 347a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "onLoadComplete: " + this); 3485e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 3492707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (mDestroyed) { 350a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, " Ignoring load complete -- destroyed"); 3512707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn return; 3522707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 3532707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 354c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn // Notify of the new data so the app can switch out the old data before 355c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn // we try to destroy it. 3560e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn if (mData != data) { 3570e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn mData = data; 3580e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn if (mStarted) { 3590e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn callOnLoadFinished(loader, data); 3600e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn } 361c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn } 362c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 363a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn //if (DEBUG) Log.v(TAG, " onLoadFinished returned: " + this); 3645e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 3655e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // We have now given the application the new loader with its 3665e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // loaded data, so it should have stopped using the previous 3675e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // loader. If there is a previous loader on the inactive list, 3685e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // clean it up. 3692707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn LoaderInfo info = mInactiveLoaders.get(mId); 3705e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn if (info != null && info != this) { 3710e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn info.mDeliveredData = null; 3725e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn info.destroy(); 3732707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mInactiveLoaders.remove(mId); 374c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 375c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 3765e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 377fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn void callOnLoadFinished(Loader<Object> loader, Object data) { 378fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn if (mCallbacks != null) { 379fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn String lastBecause = null; 380fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn if (mActivity != null) { 381fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn lastBecause = mActivity.mFragments.mNoTransactionsBecause; 382fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn mActivity.mFragments.mNoTransactionsBecause = "onLoadFinished"; 383fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } 384fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn try { 385a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, " onLoadFinished in " + loader + ": " 386a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn + loader.dataToString(data)); 387fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn mCallbacks.onLoadFinished(loader, data); 388fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } finally { 389fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn if (mActivity != null) { 390fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn mActivity.mFragments.mNoTransactionsBecause = lastBecause; 391fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } 392fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } 3930e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn mDeliveredData = data; 394fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } 395fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } 396fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn 3975e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn @Override 3985e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn public String toString() { 3995e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn StringBuilder sb = new StringBuilder(64); 4005e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn sb.append("LoaderInfo{"); 4015e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn sb.append(Integer.toHexString(System.identityHashCode(this))); 4025e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn sb.append(" #"); 4035e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn sb.append(mId); 404a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append(" : "); 405a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn DebugUtils.buildShortClassTag(mLoader, sb); 406a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append("}}"); 40730d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn return sb.toString(); 40830d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn } 40930d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn 41030d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 41130d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(prefix); writer.print("mId="); writer.print(mId); 41230d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(" mArgs="); writer.println(mArgs); 41330d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(prefix); writer.print("mCallbacks="); writer.println(mCallbacks); 41430d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(prefix); writer.print("mLoader="); writer.println(mLoader); 415a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (mLoader != null) { 416a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn mLoader.dump(prefix + " ", fd, writer, args); 417a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 41830d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(prefix); writer.print("mData="); writer.println(mData); 4190e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn writer.print(prefix); writer.print("mDeliveredData="); writer.println(mDeliveredData); 42030d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(prefix); writer.print("mStarted="); writer.print(mStarted); 42130d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(" mRetaining="); writer.print(mRetaining); 422f73c75ca20fcaaee1b0eeaaf756252c33e3099c6Dianne Hackborn writer.print(" mDestroyed="); writer.println(mDestroyed); 4230e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn writer.print(prefix); writer.print("mListenerRegistered="); 4240e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn writer.println(mListenerRegistered); 42530d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn } 426c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 427c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 428fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn LoaderManagerImpl(Activity activity, boolean started) { 429fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn mActivity = activity; 430c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn mStarted = started; 431c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 432c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 433fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn void updateActivity(Activity activity) { 434fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn mActivity = activity; 435fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } 436fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn 4372707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn private LoaderInfo createLoader(int id, Bundle args, 4382707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn LoaderManager.LoaderCallbacks<Object> callback) { 4392707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn LoaderInfo info = new LoaderInfo(id, args, (LoaderManager.LoaderCallbacks<Object>)callback); 4402707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mLoaders.put(id, info); 4412707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn Loader<Object> loader = callback.onCreateLoader(id, args); 4422707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn info.mLoader = (Loader<Object>)loader; 4432707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (mStarted) { 4444911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn // The activity will start all existing loaders in it's onStart(), 4454911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn // so only start them here if we're past that point of the activitiy's 4464911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn // life cycle 4474911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn info.start(); 4482707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 4492707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn return info; 4502707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 4512707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 4522707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn @SuppressWarnings("unchecked") 4532707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn public <D> Loader<D> initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) { 4542707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn LoaderInfo info = mLoaders.get(id); 4552707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 456a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "initLoader in " + this + ": args=" + args); 4575e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 4582707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (info == null) { 4592707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // Loader doesn't already exist; create. 4602707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn info = createLoader(id, args, (LoaderManager.LoaderCallbacks<Object>)callback); 461a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, " Created new loader " + info); 4622707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } else { 463a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, " Re-using existing loader " + info); 4642707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn info.mCallbacks = (LoaderManager.LoaderCallbacks<Object>)callback; 4652707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 4662707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 4672707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (info.mData != null && mStarted) { 4682707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // If the loader has already generated its data, report it now. 469fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn info.callOnLoadFinished(info.mLoader, info.mData); 4702707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 4712707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 4722707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn return (Loader<D>)info.mLoader; 4732707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 4742707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 475c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn @SuppressWarnings("unchecked") 4762707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn public <D> Loader<D> restartLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) { 477c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn LoaderInfo info = mLoaders.get(id); 478a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "restartLoader in " + this + ": args=" + args); 479c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn if (info != null) { 4805e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn LoaderInfo inactive = mInactiveLoaders.get(id); 4815e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn if (inactive != null) { 4825e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn if (info.mData != null) { 4835e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // This loader now has data... we are probably being 4845e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // called from within onLoadComplete, where we haven't 4855e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // yet destroyed the last inactive loader. So just do 4865e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // that now. 487a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, " Removing last inactive loader: " + info); 4880e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn inactive.mDeliveredData = null; 4895e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn inactive.destroy(); 4905e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn mInactiveLoaders.put(id, info); 4915e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn } else { 4925e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // We already have an inactive loader for this ID that we are 4935e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // waiting for! Now we have three active loaders... let's just 4945e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // drop the one in the middle, since we are still waiting for 4955e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn // its result but that result is already out of date. 496a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, " Removing intermediate loader: " + info); 4975e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn info.destroy(); 4985e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn } 4992707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } else { 5002707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // Keep track of the previous instance of this loader so we can destroy 5012707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn // it when the new one completes. 502a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, " Making last loader inactive: " + info); 5032707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mInactiveLoaders.put(id, info); 5042707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 505c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 506c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 5072707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn info = createLoader(id, args, (LoaderManager.LoaderCallbacks<Object>)callback); 5082707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn return (Loader<D>)info.mLoader; 509c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 510c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 511c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn public void destroyLoader(int id) { 512a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "destroyLoader in " + this + " of " + id); 5132707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn int idx = mLoaders.indexOfKey(id); 5142707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (idx >= 0) { 5152707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn LoaderInfo info = mLoaders.valueAt(idx); 5162707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mLoaders.removeAt(idx); 5174911b783aa9f4af5ac919db861751d350471f5efDianne Hackborn info.destroy(); 518c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 519f73c75ca20fcaaee1b0eeaaf756252c33e3099c6Dianne Hackborn idx = mInactiveLoaders.indexOfKey(id); 520f73c75ca20fcaaee1b0eeaaf756252c33e3099c6Dianne Hackborn if (idx >= 0) { 521f73c75ca20fcaaee1b0eeaaf756252c33e3099c6Dianne Hackborn LoaderInfo info = mInactiveLoaders.valueAt(idx); 522f73c75ca20fcaaee1b0eeaaf756252c33e3099c6Dianne Hackborn mInactiveLoaders.removeAt(idx); 523f73c75ca20fcaaee1b0eeaaf756252c33e3099c6Dianne Hackborn info.destroy(); 524f73c75ca20fcaaee1b0eeaaf756252c33e3099c6Dianne Hackborn } 525c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 526c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 527c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn @SuppressWarnings("unchecked") 528c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn public <D> Loader<D> getLoader(int id) { 529c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn LoaderInfo loaderInfo = mLoaders.get(id); 530c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn if (loaderInfo != null) { 5312707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn return (Loader<D>)mLoaders.get(id).mLoader; 532c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 533c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn return null; 534c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 535c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 536c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn void doStart() { 537a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "Starting in " + this); 538fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn if (mStarted) { 539fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn RuntimeException e = new RuntimeException("here"); 540fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn e.fillInStackTrace(); 541fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn Log.w(TAG, "Called doStart when already started: " + this, e); 542fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn return; 543fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } 544fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn 545c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn mStarted = true; 546c91893511dc1b9e634648406c9ae61b15476e65dDianne Hackborn 547c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn // Call out to sub classes so they can start their loaders 548c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn // Let the existing loaders know that we want to be notified when a load is complete 549c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn for (int i = mLoaders.size()-1; i >= 0; i--) { 5502707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mLoaders.valueAt(i).start(); 551c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 552c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 553c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 554c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn void doStop() { 555a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "Stopping in " + this); 556fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn if (!mStarted) { 557fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn RuntimeException e = new RuntimeException("here"); 558fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn e.fillInStackTrace(); 559fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn Log.w(TAG, "Called doStop when not started: " + this, e); 560fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn return; 561fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } 5625e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 563c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn for (int i = mLoaders.size()-1; i >= 0; i--) { 5642707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mLoaders.valueAt(i).stop(); 565c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 566c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn mStarted = false; 567c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 568c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn 5692707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn void doRetain() { 570a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "Retaining in " + this); 571fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn if (!mStarted) { 572fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn RuntimeException e = new RuntimeException("here"); 573fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn e.fillInStackTrace(); 574fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn Log.w(TAG, "Called doRetain when not started: " + this, e); 575fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn return; 576fb3cffeb35368da22f99b85d45039c4e6e471c06Dianne Hackborn } 5775e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 5782707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mRetaining = true; 5792707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mStarted = false; 5802707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn for (int i = mLoaders.size()-1; i >= 0; i--) { 5812707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mLoaders.valueAt(i).retain(); 5822707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 5832707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 5842707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 5852707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn void finishRetain() { 586a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (mRetaining) { 587a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "Finished Retaining in " + this); 5885e0d59547c4042037e23a42ba4e2521721e9c7d3Dianne Hackborn 589a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn mRetaining = false; 590a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn for (int i = mLoaders.size()-1; i >= 0; i--) { 591a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn mLoaders.valueAt(i).finishRetain(); 592a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 5932707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 5942707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 5952707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 596c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn void doDestroy() { 5972707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn if (!mRetaining) { 598a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "Destroying Active in " + this); 599c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn for (int i = mLoaders.size()-1; i >= 0; i--) { 6002707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mLoaders.valueAt(i).destroy(); 601c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 602c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 6032707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn 604a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn if (DEBUG) Log.v(TAG, "Destroying Inactive in " + this); 6052707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn for (int i = mInactiveLoaders.size()-1; i >= 0; i--) { 6062707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mInactiveLoaders.valueAt(i).destroy(); 6072707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn } 6082707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn mInactiveLoaders.clear(); 609c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn } 61030d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn 61130d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn @Override 612a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn public String toString() { 613a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn StringBuilder sb = new StringBuilder(128); 614a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append("LoaderManager{"); 615a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append(Integer.toHexString(System.identityHashCode(this))); 616a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append(" in "); 617a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn DebugUtils.buildShortClassTag(mActivity, sb); 618a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn sb.append("}}"); 619a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn return sb.toString(); 620a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn } 621a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn 622a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn @Override 62330d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 62430d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn if (mLoaders.size() > 0) { 62530d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(prefix); writer.println("Active Loaders:"); 62630d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn String innerPrefix = prefix + " "; 62730d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn for (int i=0; i < mLoaders.size(); i++) { 62830d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn LoaderInfo li = mLoaders.valueAt(i); 62930d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(prefix); writer.print(" #"); writer.print(mLoaders.keyAt(i)); 630a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn writer.print(": "); writer.println(li.toString()); 63130d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn li.dump(innerPrefix, fd, writer, args); 63230d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn } 63330d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn } 63430d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn if (mInactiveLoaders.size() > 0) { 63530d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(prefix); writer.println("Inactive Loaders:"); 63630d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn String innerPrefix = prefix + " "; 63730d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn for (int i=0; i < mInactiveLoaders.size(); i++) { 63830d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn LoaderInfo li = mInactiveLoaders.valueAt(i); 63930d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn writer.print(prefix); writer.print(" #"); writer.print(mInactiveLoaders.keyAt(i)); 640a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn writer.print(": "); writer.println(li.toString()); 64130d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn li.dump(innerPrefix, fd, writer, args); 64230d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn } 64330d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn } 64430d7189067524000c738c188c4ff91f84f474d25Dianne Hackborn } 645c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn} 646