1cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn/*
2cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Copyright (C) 2011 The Android Open Source Project
3cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *
4cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
5cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * you may not use this file except in compliance with the License.
6cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * You may obtain a copy of the License at
7cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *
8cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
9cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *
10cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
11cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
12cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * See the License for the specific language governing permissions and
14cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * limitations under the License.
15cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn */
16cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
17cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornpackage android.support.v4.app;
18cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
19cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.app.Activity;
20cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.os.Bundle;
21cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.support.v4.content.Loader;
22cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.support.v4.util.DebugUtils;
23cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.util.Log;
24cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
25cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport java.io.FileDescriptor;
26cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport java.io.PrintWriter;
27cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport java.lang.reflect.Modifier;
28cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
29cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn/**
30cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Static library support version of the framework's {@link android.app.LoaderManager}.
31cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Used to write apps that run on platforms prior to Android 3.0.  When running
32cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * on Android 3.0 or above, this implementation is still used; it does not try
33cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * to switch to the framework's implementation.  See the framework SDK
34cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * documentation for a class overview.
35cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *
36cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * <p>Your activity must derive from {@link FragmentActivity} to use this.
37cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn */
38cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornpublic abstract class LoaderManager {
39cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
40cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Callback interface for a client to interact with the manager.
41cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
42cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public interface LoaderCallbacks<D> {
43cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        /**
44cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * Instantiate and return a new Loader for the given ID.
45cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         *
46cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * @param id The ID whose loader is to be created.
47cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * @param args Any arguments supplied by the caller.
48cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * @return Return a new Loader instance that is ready to start loading.
49cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         */
50cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        public Loader<D> onCreateLoader(int id, Bundle args);
51cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
52cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        /**
53cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * Called when a previously created loader has finished its load.  Note
54cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * that normally an application is <em>not</em> allowed to commit fragment
55cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * transactions while in this call, since it can happen after an
56cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * activity's state is saved.  See {@link FragmentManager#beginTransaction()
57cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * FragmentManager.openTransaction()} for further discussion on this.
58cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         *
59cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * <p>This function is guaranteed to be called prior to the release of
60cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * the last data that was supplied for this Loader.  At this point
61cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * you should remove all use of the old data (since it will be released
62cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * soon), but should not do your own release of the data since its Loader
63cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * owns it and will take care of that.  The Loader will take care of
64cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * management of its data so you don't have to.  In particular:
65cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         *
66cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * <ul>
67cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * <li> <p>The Loader will monitor for changes to the data, and report
68cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * them to you through new calls here.  You should not monitor the
69cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * data yourself.  For example, if the data is a {@link android.database.Cursor}
70cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * and you place it in a {@link android.widget.CursorAdapter}, use
71cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * the {@link android.widget.CursorAdapter#CursorAdapter(android.content.Context,
72cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * android.database.Cursor, int)} constructor <em>without</em> passing
73cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * in either {@link android.widget.CursorAdapter#FLAG_AUTO_REQUERY}
74cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * or {@link android.widget.CursorAdapter#FLAG_REGISTER_CONTENT_OBSERVER}
75cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * (that is, use 0 for the flags argument).  This prevents the CursorAdapter
76cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * from doing its own observing of the Cursor, which is not needed since
77cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * when a change happens you will get a new Cursor throw another call
78cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * here.
79cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * <li> The Loader will release the data once it knows the application
80cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * is no longer using it.  For example, if the data is
81cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * a {@link android.database.Cursor} from a {@link android.content.CursorLoader},
82cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * you should not call close() on it yourself.  If the Cursor is being placed in a
83cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * {@link android.widget.CursorAdapter}, you should use the
84cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * {@link android.widget.CursorAdapter#swapCursor(android.database.Cursor)}
85cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * method so that the old Cursor is not closed.
86cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * </ul>
87cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         *
88cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * @param loader The Loader that has finished.
89cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * @param data The data generated by the Loader.
90cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         */
91cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        public void onLoadFinished(Loader<D> loader, D data);
92cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
93cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        /**
94cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * Called when a previously created loader is being reset, and thus
95cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * making its data unavailable.  The application should at this point
96cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * remove any references it has to the Loader's data.
97cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         *
98cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         * @param loader The Loader that is being reset.
99cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn         */
100cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        public void onLoaderReset(Loader<D> loader);
101cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
102cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
103cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
104cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Ensures a loader is initialized and active.  If the loader doesn't
105cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * already exist, one is created and (if the activity/fragment is currently
106cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * started) starts the loader.  Otherwise the last created
107cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * loader is re-used.
108cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
109cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * <p>In either case, the given callback is associated with the loader, and
110cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * will be called as the loader state changes.  If at the point of call
111cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * the caller is in its started state, and the requested loader
112cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * already exists and has generated its data, then
113cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * callback {@link LoaderCallbacks#onLoadFinished} will
114cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * be called immediately (inside of this function), so you must be prepared
115cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * for this to happen.
116cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
117cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param id A unique identifier for this loader.  Can be whatever you want.
118cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Identifiers are scoped to a particular LoaderManager instance.
119cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param args Optional arguments to supply to the loader at construction.
120cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * If a loader already exists (a new one does not need to be created), this
121cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * parameter will be ignored and the last arguments continue to be used.
122cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param callback Interface the LoaderManager will call to report about
123cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * changes in the state of the loader.  Required.
124cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
125cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public abstract <D> Loader<D> initLoader(int id, Bundle args,
126cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            LoaderManager.LoaderCallbacks<D> callback);
127cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
128cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
129cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Starts a new or restarts an existing {@link android.content.Loader} in
130cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * this manager, registers the callbacks to it,
131cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * and (if the activity/fragment is currently started) starts loading it.
132cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * If a loader with the same id has previously been
133cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * started it will automatically be destroyed when the new loader completes
134cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * its work. The callback will be delivered before the old loader
135cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * is destroyed.
136cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
137cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param id A unique identifier for this loader.  Can be whatever you want.
138cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Identifiers are scoped to a particular LoaderManager instance.
139cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param args Optional arguments to supply to the loader at construction.
140cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param callback Interface the LoaderManager will call to report about
141cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * changes in the state of the loader.  Required.
142cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
143cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public abstract <D> Loader<D> restartLoader(int id, Bundle args,
144cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            LoaderManager.LoaderCallbacks<D> callback);
145cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
146cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
147cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Stops and removes the loader with the given ID.  If this loader
148cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * had previously reported data to the client through
149cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * {@link LoaderCallbacks#onLoadFinished(Loader, Object)}, a call
150cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * will be made to {@link LoaderCallbacks#onLoaderReset(Loader)}.
151cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
152cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public abstract void destroyLoader(int id);
153cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
154cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
155cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Return the Loader with the given id or null if no matching Loader
156cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * is found.
157cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
158cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public abstract <D> Loader<D> getLoader(int id);
159cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
160cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
161cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Print the LoaderManager's state into the given stream.
162cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
163cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param prefix Text to print at the front of each line.
164cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param fd The raw file descriptor that the dump is being sent to.
165cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param writer A PrintWriter to which the dump is to be set.
166cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param args Additional arguments to the dump request.
167cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
168cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public abstract void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args);
169cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
170cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
171cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Control whether the framework's internal loader manager debugging
172cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * logs are turned on.  If enabled, you will see output in logcat as
173cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * the framework performs loader operations.
174cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
175cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public static void enableDebugLogging(boolean enabled) {
176cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        LoaderManagerImpl.DEBUG = enabled;
177cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
178abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell
179abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell    /**
180abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell     * Returns true if any loaders managed are currently running and have not
181abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell     * returned data to the application yet.
182abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell     */
183abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell    public boolean hasRunningLoaders() { return false; }
184cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn}
185cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
186cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornclass LoaderManagerImpl extends LoaderManager {
187cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    static final String TAG = "LoaderManager";
188cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    static boolean DEBUG = false;
189cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
190cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    // These are the currently active loaders.  A loader is here
191cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    // from the time its load is started until it has been explicitly
192cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    // stopped or restarted by the application.
193cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    final HCSparseArray<LoaderInfo> mLoaders = new HCSparseArray<LoaderInfo>();
194cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
195cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    // These are previously run loaders.  This list is maintained internally
196cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    // to avoid destroying a loader while an application is still using it.
197cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    // It allows an application to restart a loader, but continue using its
198cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    // previously run loader until the new loader's data is available.
199cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    final HCSparseArray<LoaderInfo> mInactiveLoaders = new HCSparseArray<LoaderInfo>();
200cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
201cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    FragmentActivity mActivity;
202cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    boolean mStarted;
203cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    boolean mRetaining;
204cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    boolean mRetainingStarted;
205cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
206cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    boolean mCreatingLoader;
207cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
208cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    final class LoaderInfo implements Loader.OnLoadCompleteListener<Object> {
209cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        final int mId;
210cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        final Bundle mArgs;
211cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        LoaderManager.LoaderCallbacks<Object> mCallbacks;
212cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        Loader<Object> mLoader;
213cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        boolean mHaveData;
214cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        boolean mDeliveredData;
215cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        Object mData;
216cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        boolean mStarted;
217cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        boolean mRetaining;
218cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        boolean mRetainingStarted;
2199c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn        boolean mReportNextStart;
220cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        boolean mDestroyed;
221cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        boolean mListenerRegistered;
222cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
223cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        LoaderInfo mPendingLoader;
224cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
225cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        public LoaderInfo(int id, Bundle args, LoaderManager.LoaderCallbacks<Object> callbacks) {
226cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mId = id;
227cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mArgs = args;
228cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mCallbacks = callbacks;
229cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
230cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
231cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        void start() {
232cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mRetaining && mRetainingStarted) {
233cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // Our owner is started, but we were being retained from a
234cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // previous instance in the started state...  so there is really
235cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // nothing to do here, since the loaders are still started.
236cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mStarted = true;
237cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                return;
238cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
239cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
240cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mStarted) {
241cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // If loader already started, don't restart.
242cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                return;
243cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
244cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
245cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mStarted = true;
246cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
247cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (DEBUG) Log.v(TAG, "  Starting: " + this);
248cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mLoader == null && mCallbacks != null) {
249cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn               mLoader = mCallbacks.onCreateLoader(mId, mArgs);
250cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
251cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mLoader != null) {
252cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (mLoader.getClass().isMemberClass()
253cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        && !Modifier.isStatic(mLoader.getClass().getModifiers())) {
254cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    throw new IllegalArgumentException(
255cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                            "Object returned from onCreateLoader must not be a non-static inner member class: "
256cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                            + mLoader);
257cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                }
258cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (!mListenerRegistered) {
259cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    mLoader.registerListener(mId, this);
260cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    mListenerRegistered = true;
261cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                }
262cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mLoader.startLoading();
263cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
264cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
265cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
266cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        void retain() {
267cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (DEBUG) Log.v(TAG, "  Retaining: " + this);
268cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mRetaining = true;
269cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mRetainingStarted = mStarted;
270cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mStarted = false;
271cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mCallbacks = null;
272cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
273cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
274cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        void finishRetain() {
275cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mRetaining) {
276cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (DEBUG) Log.v(TAG, "  Finished Retaining: " + this);
277cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mRetaining = false;
278cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (mStarted != mRetainingStarted) {
279cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    if (!mStarted) {
280cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        // This loader was retained in a started state, but
281cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        // at the end of retaining everything our owner is
282cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        // no longer started...  so make it stop.
283cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        stop();
284cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    }
285cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                }
286cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
287cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
2889c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn            if (mStarted && mHaveData && !mReportNextStart) {
289cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // This loader has retained its data, either completely across
290cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // a configuration change or just whatever the last data set
291cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // was after being restarted from a stop, and now at the point of
292cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // finishing the retain we find we remain started, have
293cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // our data, and the owner has a new callback...  so
294cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // let's deliver the data now.
295cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                callOnLoadFinished(mLoader, mData);
296cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
297cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
298cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
2999c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn        void reportStart() {
3009c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn            if (mStarted) {
3019c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn                if (mReportNextStart) {
3029c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn                    mReportNextStart = false;
3039c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn                    if (mHaveData) {
3049c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn                        callOnLoadFinished(mLoader, mData);
3059c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn                    }
3069c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn                }
3079c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn            }
3089c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn        }
3099c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn
310cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        void stop() {
311cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (DEBUG) Log.v(TAG, "  Stopping: " + this);
312cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mStarted = false;
313cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (!mRetaining) {
314cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (mLoader != null && mListenerRegistered) {
315cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    // Let the loader know we're done with it
316cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    mListenerRegistered = false;
317cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    mLoader.unregisterListener(this);
318cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    mLoader.stopLoading();
319cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                }
320cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
321cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
322cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
323cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        void destroy() {
324cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (DEBUG) Log.v(TAG, "  Destroying: " + this);
325cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mDestroyed = true;
326cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            boolean needReset = mDeliveredData;
327cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mDeliveredData = false;
328cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mCallbacks != null && mLoader != null && mHaveData && needReset) {
329cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (DEBUG) Log.v(TAG, "  Reseting: " + this);
330cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                String lastBecause = null;
331cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (mActivity != null) {
332cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    lastBecause = mActivity.mFragments.mNoTransactionsBecause;
333cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    mActivity.mFragments.mNoTransactionsBecause = "onLoaderReset";
334cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                }
335cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                try {
336cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    mCallbacks.onLoaderReset(mLoader);
337cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                } finally {
338cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    if (mActivity != null) {
339cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        mActivity.mFragments.mNoTransactionsBecause = lastBecause;
340cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    }
341cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                }
342cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
343cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mCallbacks = null;
344cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mData = null;
345cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mHaveData = false;
346cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mLoader != null) {
347cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (mListenerRegistered) {
348cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    mListenerRegistered = false;
349cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    mLoader.unregisterListener(this);
350cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                }
351cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mLoader.reset();
352cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
353cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mPendingLoader != null) {
354cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mPendingLoader.destroy();
355cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
356cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
357cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
358cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        @Override public void onLoadComplete(Loader<Object> loader, Object data) {
359cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (DEBUG) Log.v(TAG, "onLoadComplete: " + this);
360cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
361cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mDestroyed) {
362cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (DEBUG) Log.v(TAG, "  Ignoring load complete -- destroyed");
363cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                return;
364cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
365cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
366cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mLoaders.get(mId) != this) {
367cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // This data is not coming from the current active loader.
368cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // We don't care about it.
369cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (DEBUG) Log.v(TAG, "  Ignoring load complete -- not active");
370cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                return;
371cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
372cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
373cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            LoaderInfo pending = mPendingLoader;
374cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (pending != null) {
375cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // There is a new request pending and we were just
376cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // waiting for the old one to complete before starting
377cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // it.  So now it is time, switch over to the new loader.
378cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (DEBUG) Log.v(TAG, "  Switching to pending loader: " + pending);
379cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mPendingLoader = null;
380cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mLoaders.put(mId, null);
381cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                destroy();
382cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                installLoader(pending);
383cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                return;
384cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
385cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
386cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            // Notify of the new data so the app can switch out the old data before
387cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            // we try to destroy it.
388cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mData != data || !mHaveData) {
389cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mData = data;
390cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mHaveData = true;
391cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (mStarted) {
392cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    callOnLoadFinished(loader, data);
393cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                }
394cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
395cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
396cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            //if (DEBUG) Log.v(TAG, "  onLoadFinished returned: " + this);
397cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
398cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            // We have now given the application the new loader with its
399cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            // loaded data, so it should have stopped using the previous
400cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            // loader.  If there is a previous loader on the inactive list,
401cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            // clean it up.
402cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            LoaderInfo info = mInactiveLoaders.get(mId);
403cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (info != null && info != this) {
404cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                info.mDeliveredData = false;
405cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                info.destroy();
406cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mInactiveLoaders.remove(mId);
407cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
408abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell
4091199ae7067cdf8cf3eb30c057a61ae71a0aea1e5Adam Powell            if (mActivity != null && !hasRunningLoaders()) {
410abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell                mActivity.mFragments.startPendingDeferredFragments();
411abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell            }
412cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
413cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
414cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        void callOnLoadFinished(Loader<Object> loader, Object data) {
415cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mCallbacks != null) {
416cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                String lastBecause = null;
417cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (mActivity != null) {
418cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    lastBecause = mActivity.mFragments.mNoTransactionsBecause;
419cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    mActivity.mFragments.mNoTransactionsBecause = "onLoadFinished";
420cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                }
421cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                try {
422cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    if (DEBUG) Log.v(TAG, "  onLoadFinished in " + loader + ": "
423cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                            + loader.dataToString(data));
424cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    mCallbacks.onLoadFinished(loader, data);
425cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                } finally {
426cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    if (mActivity != null) {
427cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        mActivity.mFragments.mNoTransactionsBecause = lastBecause;
428cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    }
429cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                }
430cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mDeliveredData = true;
431cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
432cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
433cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
434cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        @Override
435cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        public String toString() {
436cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            StringBuilder sb = new StringBuilder(64);
437cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            sb.append("LoaderInfo{");
438cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            sb.append(Integer.toHexString(System.identityHashCode(this)));
439cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            sb.append(" #");
440cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            sb.append(mId);
441cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            sb.append(" : ");
442cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            DebugUtils.buildShortClassTag(mLoader, sb);
443cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            sb.append("}}");
444cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            return sb.toString();
445cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
446cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
447cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
448cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            writer.print(prefix); writer.print("mId="); writer.print(mId);
449cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    writer.print(" mArgs="); writer.println(mArgs);
450cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            writer.print(prefix); writer.print("mCallbacks="); writer.println(mCallbacks);
451cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            writer.print(prefix); writer.print("mLoader="); writer.println(mLoader);
452cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mLoader != null) {
453cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mLoader.dump(prefix + "  ", fd, writer, args);
454cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
455cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mHaveData || mDeliveredData) {
456cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                writer.print(prefix); writer.print("mHaveData="); writer.print(mHaveData);
457cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        writer.print("  mDeliveredData="); writer.println(mDeliveredData);
458cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                writer.print(prefix); writer.print("mData="); writer.println(mData);
459cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
460cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            writer.print(prefix); writer.print("mStarted="); writer.print(mStarted);
4619c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn                    writer.print(" mReportNextStart="); writer.print(mReportNextStart);
462cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    writer.print(" mDestroyed="); writer.println(mDestroyed);
4639c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn            writer.print(prefix); writer.print("mRetaining="); writer.print(mRetaining);
4649c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn                    writer.print(" mRetainingStarted="); writer.print(mRetainingStarted);
4659c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn                    writer.print(" mListenerRegistered="); writer.println(mListenerRegistered);
466cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mPendingLoader != null) {
467cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                writer.print(prefix); writer.println("Pending Loader ");
468cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        writer.print(mPendingLoader); writer.println(":");
469cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mPendingLoader.dump(prefix + "  ", fd, writer, args);
470cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
471cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
472cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
473cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
474cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    LoaderManagerImpl(FragmentActivity activity, boolean started) {
475cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mActivity = activity;
476cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mStarted = started;
477cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
478cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
479cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    void updateActivity(FragmentActivity activity) {
480cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mActivity = activity;
481cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
482cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
483cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    private LoaderInfo createLoader(int id, Bundle args,
484cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            LoaderManager.LoaderCallbacks<Object> callback) {
485cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        LoaderInfo info = new LoaderInfo(id, args,  (LoaderManager.LoaderCallbacks<Object>)callback);
486cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        Loader<Object> loader = callback.onCreateLoader(id, args);
487cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        info.mLoader = (Loader<Object>)loader;
488cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return info;
489cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
490cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
491cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    private LoaderInfo createAndInstallLoader(int id, Bundle args,
492cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            LoaderManager.LoaderCallbacks<Object> callback) {
493cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        try {
494cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mCreatingLoader = true;
495cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            LoaderInfo info = createLoader(id, args, callback);
496cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            installLoader(info);
497cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            return info;
498cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        } finally {
499cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mCreatingLoader = false;
500cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
501cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
502cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
503cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    void installLoader(LoaderInfo info) {
504cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mLoaders.put(info.mId, info);
505cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mStarted) {
506cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            // The activity will start all existing loaders in it's onStart(),
507cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            // so only start them here if we're past that point of the activitiy's
508cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            // life cycle
509cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            info.start();
510cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
511cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
512cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
513cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
514cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Call to initialize a particular ID with a Loader.  If this ID already
515cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * has a Loader associated with it, it is left unchanged and any previous
516cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * callbacks replaced with the newly provided ones.  If there is not currently
517cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * a Loader for the ID, a new one is created and started.
518cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
519cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * <p>This function should generally be used when a component is initializing,
520cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * to ensure that a Loader it relies on is created.  This allows it to re-use
521cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * an existing Loader's data if there already is one, so that for example
522cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * when an {@link Activity} is re-created after a configuration change it
523cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * does not need to re-create its loaders.
524cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
525cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * <p>Note that in the case where an existing Loader is re-used, the
526cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * <var>args</var> given here <em>will be ignored</em> because you will
527cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * continue using the previous Loader.
528cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
529cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param id A unique (to this LoaderManager instance) identifier under
530cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * which to manage the new Loader.
531cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param args Optional arguments that will be propagated to
532cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * {@link LoaderCallbacks#onCreateLoader(int, Bundle) LoaderCallbacks.onCreateLoader()}.
533cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param callback Interface implementing management of this Loader.  Required.
534cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Its onCreateLoader() method will be called while inside of the function to
535cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * instantiate the Loader object.
536cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
537cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    @SuppressWarnings("unchecked")
538cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public <D> Loader<D> initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {
539cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mCreatingLoader) {
540cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            throw new IllegalStateException("Called while creating a loader");
541cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
542cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
543cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        LoaderInfo info = mLoaders.get(id);
544cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
545cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (DEBUG) Log.v(TAG, "initLoader in " + this + ": args=" + args);
546cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
547cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (info == null) {
548cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            // Loader doesn't already exist; create.
549cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            info = createAndInstallLoader(id, args,  (LoaderManager.LoaderCallbacks<Object>)callback);
550cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (DEBUG) Log.v(TAG, "  Created new loader " + info);
551cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        } else {
552cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (DEBUG) Log.v(TAG, "  Re-using existing loader " + info);
553cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            info.mCallbacks = (LoaderManager.LoaderCallbacks<Object>)callback;
554cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
555cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
556cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (info.mHaveData && mStarted) {
557cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            // If the loader has already generated its data, report it now.
558cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            info.callOnLoadFinished(info.mLoader, info.mData);
559cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
560cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
561cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return (Loader<D>)info.mLoader;
562cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
563cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
564cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
565cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Call to re-create the Loader associated with a particular ID.  If there
566cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * is currently a Loader associated with this ID, it will be
567cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * canceled/stopped/destroyed as appropriate.  A new Loader with the given
568cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * arguments will be created and its data delivered to you once available.
569cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
570cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * <p>This function does some throttling of Loaders.  If too many Loaders
571cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * have been created for the given ID but not yet generated their data,
572cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * new calls to this function will create and return a new Loader but not
573cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * actually start it until some previous loaders have completed.
574cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
575cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * <p>After calling this function, any previous Loaders associated with
576cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * this ID will be considered invalid, and you will receive no further
577cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * data updates from them.
578cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
579cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param id A unique (to this LoaderManager instance) identifier under
580cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * which to manage the new Loader.
581cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param args Optional arguments that will be propagated to
582cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * {@link LoaderCallbacks#onCreateLoader(int, Bundle) LoaderCallbacks.onCreateLoader()}.
583cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param callback Interface implementing management of this Loader.  Required.
584cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Its onCreateLoader() method will be called while inside of the function to
585cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * instantiate the Loader object.
586cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
587cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    @SuppressWarnings("unchecked")
588cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public <D> Loader<D> restartLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {
589cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mCreatingLoader) {
590cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            throw new IllegalStateException("Called while creating a loader");
591cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
592cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
593cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        LoaderInfo info = mLoaders.get(id);
594cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (DEBUG) Log.v(TAG, "restartLoader in " + this + ": args=" + args);
595cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (info != null) {
596cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            LoaderInfo inactive = mInactiveLoaders.get(id);
597cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (inactive != null) {
598cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (info.mHaveData) {
599cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    // This loader now has data...  we are probably being
600cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    // called from within onLoadComplete, where we haven't
601cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    // yet destroyed the last inactive loader.  So just do
602cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    // that now.
603cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    if (DEBUG) Log.v(TAG, "  Removing last inactive loader: " + info);
604cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    inactive.mDeliveredData = false;
605cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    inactive.destroy();
606cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    info.mLoader.abandon();
607cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    mInactiveLoaders.put(id, info);
608cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                } else {
609cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    // We already have an inactive loader for this ID that we are
610cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    // waiting for!  What to do, what to do...
611cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    if (!info.mStarted) {
612cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        // The current Loader has not been started...  we thus
613cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        // have no reason to keep it around, so bam, slam,
614cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        // thank-you-ma'am.
615cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        if (DEBUG) Log.v(TAG, "  Current loader is stopped; replacing");
616cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        mLoaders.put(id, null);
617cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        info.destroy();
618cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    } else {
619cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        // Now we have three active loaders... we'll queue
620cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        // up this request to be processed once one of the other loaders
621cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        // finishes.
622cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        if (info.mPendingLoader != null) {
623cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                            if (DEBUG) Log.v(TAG, "  Removing pending loader: " + info.mPendingLoader);
624cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                            info.mPendingLoader.destroy();
625cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                            info.mPendingLoader = null;
626cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        }
627cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        if (DEBUG) Log.v(TAG, "  Enqueuing as new pending loader");
628cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        info.mPendingLoader = createLoader(id, args,
629cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                                (LoaderManager.LoaderCallbacks<Object>)callback);
630cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        return (Loader<D>)info.mPendingLoader.mLoader;
631cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    }
632cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                }
633cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            } else {
634cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // Keep track of the previous instance of this loader so we can destroy
635cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // it when the new one completes.
636cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (DEBUG) Log.v(TAG, "  Making last loader inactive: " + info);
637cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                info.mLoader.abandon();
638cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mInactiveLoaders.put(id, info);
639cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
640cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
641cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
642cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        info = createAndInstallLoader(id, args,  (LoaderManager.LoaderCallbacks<Object>)callback);
643cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return (Loader<D>)info.mLoader;
644cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
645cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
646cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
647cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Rip down, tear apart, shred to pieces a current Loader ID.  After returning
648cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * from this function, any Loader objects associated with this ID are
649cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * destroyed.  Any data associated with them is destroyed.  You better not
650cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * be using it when you do this.
651cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param id Identifier of the Loader to be destroyed.
652cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
653cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void destroyLoader(int id) {
654cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mCreatingLoader) {
655cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            throw new IllegalStateException("Called while creating a loader");
656cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
657cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
658cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (DEBUG) Log.v(TAG, "destroyLoader in " + this + " of " + id);
659cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        int idx = mLoaders.indexOfKey(id);
660cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (idx >= 0) {
661cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            LoaderInfo info = mLoaders.valueAt(idx);
662cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mLoaders.removeAt(idx);
663cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            info.destroy();
664cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
665cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        idx = mInactiveLoaders.indexOfKey(id);
666cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (idx >= 0) {
667cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            LoaderInfo info = mInactiveLoaders.valueAt(idx);
668cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mInactiveLoaders.removeAt(idx);
669cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            info.destroy();
670cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
6711199ae7067cdf8cf3eb30c057a61ae71a0aea1e5Adam Powell        if (mActivity != null && !hasRunningLoaders()) {
6721199ae7067cdf8cf3eb30c057a61ae71a0aea1e5Adam Powell            mActivity.mFragments.startPendingDeferredFragments();
6731199ae7067cdf8cf3eb30c057a61ae71a0aea1e5Adam Powell        }
674cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
675cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
676cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
677cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Return the most recent Loader object associated with the
678cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * given ID.
679cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
680cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    @SuppressWarnings("unchecked")
681cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public <D> Loader<D> getLoader(int id) {
682cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mCreatingLoader) {
683cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            throw new IllegalStateException("Called while creating a loader");
684cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
685cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
686cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        LoaderInfo loaderInfo = mLoaders.get(id);
687cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (loaderInfo != null) {
688cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (loaderInfo.mPendingLoader != null) {
689cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                return (Loader<D>)loaderInfo.mPendingLoader.mLoader;
690cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
691cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            return (Loader<D>)loaderInfo.mLoader;
692cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
693cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return null;
694cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
695cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
696cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    void doStart() {
697cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (DEBUG) Log.v(TAG, "Starting in " + this);
698cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mStarted) {
699cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            RuntimeException e = new RuntimeException("here");
700cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            e.fillInStackTrace();
701cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            Log.w(TAG, "Called doStart when already started: " + this, e);
702cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            return;
703cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
704cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
705cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mStarted = true;
706cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
707cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        // Call out to sub classes so they can start their loaders
708cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        // Let the existing loaders know that we want to be notified when a load is complete
709cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        for (int i = mLoaders.size()-1; i >= 0; i--) {
710cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mLoaders.valueAt(i).start();
711cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
712cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
713cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
714cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    void doStop() {
715cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (DEBUG) Log.v(TAG, "Stopping in " + this);
716cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (!mStarted) {
717cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            RuntimeException e = new RuntimeException("here");
718cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            e.fillInStackTrace();
719cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            Log.w(TAG, "Called doStop when not started: " + this, e);
720cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            return;
721cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
722cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
723cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        for (int i = mLoaders.size()-1; i >= 0; i--) {
724cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mLoaders.valueAt(i).stop();
725cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
726cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mStarted = false;
727cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
728cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
729cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    void doRetain() {
730cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (DEBUG) Log.v(TAG, "Retaining in " + this);
731cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (!mStarted) {
732cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            RuntimeException e = new RuntimeException("here");
733cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            e.fillInStackTrace();
734cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            Log.w(TAG, "Called doRetain when not started: " + this, e);
735cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            return;
736cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
737cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
738cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mRetaining = true;
739cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mStarted = false;
740cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        for (int i = mLoaders.size()-1; i >= 0; i--) {
741cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mLoaders.valueAt(i).retain();
742cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
743cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
744cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
745cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    void finishRetain() {
746cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mRetaining) {
747cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (DEBUG) Log.v(TAG, "Finished Retaining in " + this);
748cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
749cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mRetaining = false;
750cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            for (int i = mLoaders.size()-1; i >= 0; i--) {
751cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mLoaders.valueAt(i).finishRetain();
752cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
753cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
754cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
755cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
7569c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn    void doReportNextStart() {
7579c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn        for (int i = mLoaders.size()-1; i >= 0; i--) {
7589c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn            mLoaders.valueAt(i).mReportNextStart = true;
7599c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn        }
7609c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn    }
7619c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn
7629c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn    void doReportStart() {
7639c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn        for (int i = mLoaders.size()-1; i >= 0; i--) {
7649c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn            mLoaders.valueAt(i).reportStart();
7659c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn        }
7669c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn    }
7679c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn
768cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    void doDestroy() {
769cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (!mRetaining) {
770cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (DEBUG) Log.v(TAG, "Destroying Active in " + this);
771cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            for (int i = mLoaders.size()-1; i >= 0; i--) {
772cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mLoaders.valueAt(i).destroy();
773cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
774cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
775cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
776cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (DEBUG) Log.v(TAG, "Destroying Inactive in " + this);
777cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        for (int i = mInactiveLoaders.size()-1; i >= 0; i--) {
778cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mInactiveLoaders.valueAt(i).destroy();
779cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
780cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mInactiveLoaders.clear();
781cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
782cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
783cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    @Override
784cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public String toString() {
785cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        StringBuilder sb = new StringBuilder(128);
786cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        sb.append("LoaderManager{");
787cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        sb.append(Integer.toHexString(System.identityHashCode(this)));
788cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        sb.append(" in ");
789cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        DebugUtils.buildShortClassTag(mActivity, sb);
790cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        sb.append("}}");
791cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return sb.toString();
792cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
793cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
794cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    @Override
795cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
796cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mLoaders.size() > 0) {
797cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            writer.print(prefix); writer.println("Active Loaders:");
798cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            String innerPrefix = prefix + "    ";
799cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            for (int i=0; i < mLoaders.size(); i++) {
800cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                LoaderInfo li = mLoaders.valueAt(i);
801cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                writer.print(prefix); writer.print("  #"); writer.print(mLoaders.keyAt(i));
802cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        writer.print(": "); writer.println(li.toString());
803cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                li.dump(innerPrefix, fd, writer, args);
804cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
805cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
806cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mInactiveLoaders.size() > 0) {
807cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            writer.print(prefix); writer.println("Inactive Loaders:");
808cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            String innerPrefix = prefix + "    ";
809cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            for (int i=0; i < mInactiveLoaders.size(); i++) {
810cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                LoaderInfo li = mInactiveLoaders.valueAt(i);
811cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                writer.print(prefix); writer.print("  #"); writer.print(mInactiveLoaders.keyAt(i));
812cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        writer.print(": "); writer.println(li.toString());
813cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                li.dump(innerPrefix, fd, writer, args);
814cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
815cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
816cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
817abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell
818abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell    @Override
819abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell    public boolean hasRunningLoaders() {
820abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell        boolean loadersRunning = false;
821abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell        final int count = mLoaders.size();
822abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell        for (int i = 0; i < count; i++) {
823abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell            final LoaderInfo li = mLoaders.valueAt(i);
824abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell            loadersRunning |= li.mStarted && !li.mDeliveredData;
825abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell        }
826abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell        return loadersRunning;
827abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell    }
828cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn}
829