LoaderManager.java revision 2707d6026240bcca6f0e35e2e1138958882e90ce
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.content.Loader.OnLoadCompleteListener;
21c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackbornimport android.os.Bundle;
22c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackbornimport android.util.SparseArray;
23c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn
24c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn/**
25c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn * Object associated with an {@link Activity} or {@link Fragment} for managing
26c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn * one or more {@link android.content.Loader} instances associated with it.
27c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn */
28c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackbornpublic class LoaderManager {
292707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn    final SparseArray<LoaderInfo> mLoaders = new SparseArray<LoaderInfo>();
302707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn    final SparseArray<LoaderInfo> mInactiveLoaders = new SparseArray<LoaderInfo>();
312707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn    boolean mStarted;
322707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn    boolean mRetaining;
332707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn    boolean mRetainingStarted;
342707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn
35c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    /**
36c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn     * Callback interface for a client to interact with the manager.
37c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn     */
38c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    public interface LoaderCallbacks<D> {
39c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        public Loader<D> onCreateLoader(int id, Bundle args);
40c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        public void onLoadFinished(Loader<D> loader, D data);
41c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    }
42c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn
43c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    final class LoaderInfo implements Loader.OnLoadCompleteListener<Object> {
442707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        final int mId;
452707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        final Bundle mArgs;
462707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        LoaderManager.LoaderCallbacks<Object> mCallbacks;
472707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        Loader<Object> mLoader;
482707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        Object mData;
492707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        boolean mStarted;
502707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        boolean mRetaining;
512707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        boolean mRetainingStarted;
522707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        boolean mDestroyed;
532707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        boolean mListenerRegistered;
542707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn
552707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        public LoaderInfo(int id, Bundle args, LoaderManager.LoaderCallbacks<Object> callbacks) {
562707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            mId = id;
572707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            mArgs = args;
582707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            mCallbacks = callbacks;
592707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        }
602707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn
612707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        void start() {
622707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            if (mRetaining && mRetainingStarted) {
632707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                // Our owner is started, but we were being retained from a
642707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                // previous instance in the started state...  so there is really
652707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                // nothing to do here, since the loaders are still started.
662707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                mStarted = true;
672707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                return;
682707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            }
692707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn
702707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            if (mLoader == null && mCallbacks != null) {
712707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn               mLoader = mCallbacks.onCreateLoader(mId, mArgs);
722707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            }
732707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            if (mLoader != null) {
742707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                mLoader.registerListener(mId, this);
752707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                mListenerRegistered = true;
762707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                mLoader.startLoading();
772707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                mStarted = true;
782707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            }
792707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        }
802707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn
812707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        void retain() {
822707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            mRetaining = true;
832707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            mRetainingStarted = mStarted;
842707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            mStarted = false;
852707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            mCallbacks = null;
862707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        }
872707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn
882707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        void finishRetain() {
892707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            if (mRetaining) {
902707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                mRetaining = false;
912707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                if (mStarted != mRetainingStarted) {
922707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                    if (!mStarted) {
932707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                        // This loader was retained in a started state, but
942707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                        // at the end of retaining everything our owner is
952707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                        // no longer started...  so make it stop.
962707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                        stop();
972707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                    }
982707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                }
992707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                if (mStarted && mData != null && mCallbacks != null) {
1002707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                    // This loader was retained, and now at the point of
1012707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                    // finishing the retain we find we remain started, have
1022707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                    // our data, and the owner has a new callback...  so
1032707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                    // let's deliver the data now.
1042707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                    mCallbacks.onLoadFinished(mLoader, mData);
1052707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                }
1062707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            }
1072707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        }
1082707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn
1092707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        void stop() {
1102707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            mStarted = false;
1112707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            if (mLoader != null && mListenerRegistered) {
1122707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                // Let the loader know we're done with it
1132707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                mListenerRegistered = false;
1142707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                mLoader.unregisterListener(this);
1152707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            }
1162707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        }
1172707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn
1182707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        void destroy() {
1192707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            mDestroyed = true;
1202707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            mCallbacks = null;
1212707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            if (mLoader != null) {
1222707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                if (mListenerRegistered) {
1232707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                    mListenerRegistered = false;
1242707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                    mLoader.unregisterListener(this);
1252707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                }
1262707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                mLoader.destroy();
1272707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            }
1282707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        }
129c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn
130c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        @Override public void onLoadComplete(Loader<Object> loader, Object data) {
1312707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            if (mDestroyed) {
1322707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                return;
1332707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            }
1342707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn
135c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn            // Notify of the new data so the app can switch out the old data before
136c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn            // we try to destroy it.
1372707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            mData = data;
1382707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            if (mCallbacks != null) {
1392707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                mCallbacks.onLoadFinished(loader, data);
1402707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            }
141c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn
142c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn            // Look for an inactive loader and destroy it if found
1432707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            LoaderInfo info = mInactiveLoaders.get(mId);
144c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn            if (info != null) {
1452707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                Loader<Object> oldLoader = info.mLoader;
146c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn                if (oldLoader != null) {
1472707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                    oldLoader.unregisterListener(info);
148c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn                    oldLoader.destroy();
149c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn                }
1502707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                mInactiveLoaders.remove(mId);
151c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn            }
152c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        }
153c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    }
154c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn
155c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    LoaderManager(boolean started) {
156c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        mStarted = started;
157c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    }
158c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn
1592707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn    private LoaderInfo createLoader(int id, Bundle args,
1602707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            LoaderManager.LoaderCallbacks<Object> callback) {
1612707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        LoaderInfo info = new LoaderInfo(id, args,  (LoaderManager.LoaderCallbacks<Object>)callback);
1622707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        mLoaders.put(id, info);
1632707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        Loader<Object> loader = callback.onCreateLoader(id, args);
1642707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        info.mLoader = (Loader<Object>)loader;
1652707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        if (mStarted) {
1662707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            // The activity will start all existing loaders in it's onStart(), so only start them
1672707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            // here if we're past that point of the activitiy's life cycle
1682707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            loader.registerListener(id, info);
1692707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            loader.startLoading();
1702707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        }
1712707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        return info;
1722707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn    }
1732707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn
1742707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn    /**
1752707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn     * Ensures a loader is initialized an active.  If the loader doesn't
1762707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn     * already exist, one is created and started.  Otherwise the last created
1772707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn     * loader is re-used.
1782707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn     *
1792707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn     * <p>In either case, the given callback is associated with the loader, and
1802707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn     * will be called as the loader state changes.  If at the point of call
1812707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn     * the caller is in its started state, and the requested loader
1822707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn     * already exists and has generated its data, then
1832707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn     * callback.{@link LoaderCallbacks#onLoadFinished(Loader, Object)} will
1842707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn     * be called immediately (inside of this function), so you must be prepared
1852707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn     * for this to happen.
1862707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn     */
1872707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn    @SuppressWarnings("unchecked")
1882707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn    public <D> Loader<D> initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {
1892707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        LoaderInfo info = mLoaders.get(id);
1902707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn
1912707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        if (info == null) {
1922707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            // Loader doesn't already exist; create.
1932707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            info = createLoader(id, args,  (LoaderManager.LoaderCallbacks<Object>)callback);
1942707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        } else {
1952707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            info.mCallbacks = (LoaderManager.LoaderCallbacks<Object>)callback;
1962707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        }
1972707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn
1982707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        if (info.mData != null && mStarted) {
1992707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            // If the loader has already generated its data, report it now.
2002707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            info.mCallbacks.onLoadFinished(info.mLoader, info.mData);
2012707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        }
2022707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn
2032707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        return (Loader<D>)info.mLoader;
2042707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn    }
2052707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn
206c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    /**
2072707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn     * Create a new loader in this manager, registers the callbacks to it,
208c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn     * and starts it loading.  If a loader with the same id has previously been
209c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn     * started it will automatically be destroyed when the new loader completes
210c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn     * its work. The callback will be delivered before the old loader
211c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn     * is destroyed.
212c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn     */
213c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    @SuppressWarnings("unchecked")
2142707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn    public <D> Loader<D> restartLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {
215c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        LoaderInfo info = mLoaders.get(id);
216c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        if (info != null) {
2172707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            if (mInactiveLoaders.get(id) != null) {
2182707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                // We already have an inactive loader for this ID that we are
2192707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                // waiting for!  Now we have three active loaders... let's just
2202707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                // drop the one in the middle, since we are still waiting for
2212707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                // its result but that result is already out of date.
2222707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                info.destroy();
2232707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            } else {
2242707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                // Keep track of the previous instance of this loader so we can destroy
2252707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                // it when the new one completes.
2262707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                mInactiveLoaders.put(id, info);
2272707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            }
228c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        }
229c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn
2302707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        info = createLoader(id, args,  (LoaderManager.LoaderCallbacks<Object>)callback);
2312707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        return (Loader<D>)info.mLoader;
232c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    }
233c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn
234c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    /**
235c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn     * Stops and removes the loader with the given ID.
236c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn     */
2372707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn    public void stopLoader(int id) {
2382707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        int idx = mLoaders.indexOfKey(id);
2392707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        if (idx >= 0) {
2402707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            LoaderInfo info = mLoaders.valueAt(idx);
2412707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            mLoaders.removeAt(idx);
2422707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            Loader<Object> loader = info.mLoader;
2432707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            if (loader != null) {
2442707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                loader.unregisterListener(info);
2452707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                loader.destroy();
246c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn            }
247c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        }
248c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    }
249c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn
250c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    /**
25153c67c8dfd4fe089bae2ab28cf6eae02ab1066c1Dianne Hackborn     * Return the Loader with the given id or null if no matching Loader
252c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn     * is found.
253c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn     */
254c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    @SuppressWarnings("unchecked")
255c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    public <D> Loader<D> getLoader(int id) {
256c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        LoaderInfo loaderInfo = mLoaders.get(id);
257c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        if (loaderInfo != null) {
2582707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            return (Loader<D>)mLoaders.get(id).mLoader;
259c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        }
260c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        return null;
261c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    }
262c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn
263c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    void doStart() {
264c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        // Call out to sub classes so they can start their loaders
265c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        // Let the existing loaders know that we want to be notified when a load is complete
266c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        for (int i = mLoaders.size()-1; i >= 0; i--) {
2672707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            mLoaders.valueAt(i).start();
268c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        }
269c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        mStarted = true;
270c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    }
271c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn
272c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    void doStop() {
273c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        for (int i = mLoaders.size()-1; i >= 0; i--) {
2742707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            mLoaders.valueAt(i).stop();
275c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        }
276c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        mStarted = false;
277c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    }
278c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn
2792707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn    void doRetain() {
2802707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        mRetaining = true;
2812707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        mStarted = false;
2822707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        for (int i = mLoaders.size()-1; i >= 0; i--) {
2832707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            mLoaders.valueAt(i).retain();
2842707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        }
2852707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn    }
2862707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn
2872707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn    void finishRetain() {
2882707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        mRetaining = false;
2892707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        for (int i = mLoaders.size()-1; i >= 0; i--) {
2902707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            mLoaders.valueAt(i).finishRetain();
2912707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        }
2922707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn    }
2932707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn
294c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    void doDestroy() {
2952707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        if (!mRetaining) {
296c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn            for (int i = mLoaders.size()-1; i >= 0; i--) {
2972707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn                mLoaders.valueAt(i).destroy();
298c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn            }
299c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn        }
3002707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn
3012707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        for (int i = mInactiveLoaders.size()-1; i >= 0; i--) {
3022707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn            mInactiveLoaders.valueAt(i).destroy();
3032707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        }
3042707d6026240bcca6f0e35e2e1138958882e90ceDianne Hackborn        mInactiveLoaders.clear();
305c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn    }
306c801768e4d29667a2608695449ebc2833ba0f200Dianne Hackborn}
307