19911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton/*
29911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * Copyright (C) 2010 The Android Open Source Project
39911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton *
49911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * Licensed under the Apache License, Version 2.0 (the "License");
59911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * you may not use this file except in compliance with the License.
69911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * You may obtain a copy of the License at
79911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton *
89911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton *      http://www.apache.org/licenses/LICENSE-2.0
99911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton *
109911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * Unless required by applicable law or agreed to in writing, software
119911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * distributed under the License is distributed on an "AS IS" BASIS,
129911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * See the License for the specific language governing permissions and
149911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * limitations under the License.
159911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */
169911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton
179911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamiltonpackage android.content;
189911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton
199911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamiltonimport android.os.AsyncTask;
20247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackbornimport android.os.Handler;
21a7771df3696954f0e279407e8894a916a7cb26ccJeff Brownimport android.os.OperationCanceledException;
22247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackbornimport android.os.SystemClock;
23c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brownimport android.util.Log;
24247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackbornimport android.util.TimeUtils;
25cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov
26247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackbornimport java.io.FileDescriptor;
27247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackbornimport java.io.PrintWriter;
2859d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikovimport java.util.concurrent.CountDownLatch;
29d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkeyimport java.util.concurrent.Executor;
309911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton
319911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton/**
329567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * Abstract Loader that provides an {@link AsyncTask} to do the work.  See
339567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * {@link Loader} and {@link android.app.LoaderManager} for more details.
349567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn *
359567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * <p>Here is an example implementation of an AsyncTaskLoader subclass that
369567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * loads the currently installed applications from the package manager.  This
379567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * implementation takes care of retrieving the application labels and sorting
389567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * its result set from them, monitoring for changes to the installed
399567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * applications, and rebuilding the list when a change in configuration requires
409567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * this (such as a locale change).
419567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn *
429567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/LoaderCustom.java
439567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn *      loader}
449567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn *
459567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * <p>An example implementation of a fragment that uses the above loader to show
469567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * the currently installed applications in a list is below.
479567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn *
489567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/LoaderCustom.java
499567a66a5e6f49dd8495fb5f6e2efb9f32e84b35Dianne Hackborn *      fragment}
50bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov *
519911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * @param <D> the data type to be loaded.
520a1feb819234ae7fc8cc32aa1dc5929823b0a5bcIan Lake *
531f4e67b6e17e9b86151140174491b2360bac82d9Ian Lake * @deprecated Use the <a href="{@docRoot}tools/extras/support-library.html">Support Library</a>
541f4e67b6e17e9b86151140174491b2360bac82d9Ian Lake *      {@link android.support.v4.content.AsyncTaskLoader}
559911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */
560a1feb819234ae7fc8cc32aa1dc5929823b0a5bcIan Lake@Deprecated
579911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamiltonpublic abstract class AsyncTaskLoader<D> extends Loader<D> {
58540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn    static final String TAG = "AsyncTaskLoader";
59540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn    static final boolean DEBUG = false;
60cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov
61247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    final class LoadTask extends AsyncTask<Void, Void, D> implements Runnable {
62b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown        private final CountDownLatch mDone = new CountDownLatch(1);
63bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov
64b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown        // Set to true to indicate that the task has been posted to a handler for
65b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown        // execution at a later time.  Used to throttle updates.
66247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        boolean waiting;
67bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov
689911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        /* Runs on a worker thread */
699911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        @Override
709911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        protected D doInBackground(Void... params) {
71c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown            if (DEBUG) Log.v(TAG, this + " >>> doInBackground");
72b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown            try {
73b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown                D data = AsyncTaskLoader.this.onLoadInBackground();
74c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown                if (DEBUG) Log.v(TAG, this + "  <<< doInBackground");
75b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown                return data;
76b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown            } catch (OperationCanceledException ex) {
77b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown                if (!isCancelled()) {
78b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown                    // onLoadInBackground threw a canceled exception spuriously.
79b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown                    // This is problematic because it means that the LoaderManager did not
80b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown                    // cancel the Loader itself and still expects to receive a result.
81b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown                    // Additionally, the Loader's own state will not have been updated to
82b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown                    // reflect the fact that the task was being canceled.
83b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown                    // So we treat this case as an unhandled exception.
84b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown                    throw ex;
85b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown                }
86c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown                if (DEBUG) Log.v(TAG, this + "  <<< doInBackground (was canceled)", ex);
87b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown                return null;
88b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown            }
899911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        }
909911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton
919911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        /* Runs on the UI thread */
929911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        @Override
939911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        protected void onPostExecute(D data) {
94c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown            if (DEBUG) Log.v(TAG, this + " onPostExecute");
9559d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov            try {
9659d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov                AsyncTaskLoader.this.dispatchOnLoadComplete(this, data);
9759d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov            } finally {
98b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown                mDone.countDown();
9959d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov            }
1009911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        }
101bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov
102b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown        /* Runs on the UI thread */
103bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov        @Override
104b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown        protected void onCancelled(D data) {
105c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown            if (DEBUG) Log.v(TAG, this + " onCancelled");
10659d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov            try {
107b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown                AsyncTaskLoader.this.dispatchOnCancelled(this, data);
10859d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov            } finally {
109b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown                mDone.countDown();
11059d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov            }
111247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        }
112247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn
113b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown        /* Runs on the UI thread, when the waiting task is posted to a handler.
114b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown         * This method is only executed when task execution was deferred (waiting was true). */
115247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        @Override
116247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        public void run() {
117247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            waiting = false;
118247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            AsyncTaskLoader.this.executePendingTask();
119bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov        }
120b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown
121b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown        /* Used for testing purposes to wait for the task to complete. */
122b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown        public void waitForLoader() {
123b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown            try {
124b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown                mDone.await();
125b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown            } catch (InterruptedException e) {
126b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown                // Ignore
127b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown            }
128b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown        }
1299911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton    }
1309911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton
131d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey    private final Executor mExecutor;
132d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey
133cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov    volatile LoadTask mTask;
134247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    volatile LoadTask mCancellingTask;
135247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn
136247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    long mUpdateThrottle;
137247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    long mLastLoadCompleteTime = -10000;
138247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    Handler mHandler;
1399911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton
1409911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton    public AsyncTaskLoader(Context context) {
141d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey        this(context, AsyncTask.THREAD_POOL_EXECUTOR);
142d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey    }
143d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey
144d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey    /** {@hide} */
145d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey    public AsyncTaskLoader(Context context, Executor executor) {
1469911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        super(context);
147d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey        mExecutor = executor;
1489911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton    }
1499911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton
150247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    /**
151247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * Set amount to throttle updates by.  This is the minimum time from
152b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * when the last {@link #loadInBackground()} call has completed until
153247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * a new load is scheduled.
154247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     *
155247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * @param delayMS Amount of delay, in milliseconds.
156247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     */
157247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    public void setUpdateThrottle(long delayMS) {
158247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        mUpdateThrottle = delayMS;
159247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        if (delayMS != 0) {
160247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            mHandler = new Handler();
161247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        }
162247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    }
163247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn
1649911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton    @Override
165a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn    protected void onForceLoad() {
1660e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn        super.onForceLoad();
167bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov        cancelLoad();
1689911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        mTask = new LoadTask();
169c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown        if (DEBUG) Log.v(TAG, "Preparing load: mTask=" + mTask);
170247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        executePendingTask();
1719911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton    }
1729911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton
173b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown    @Override
174b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown    protected boolean onCancelLoad() {
175c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown        if (DEBUG) Log.v(TAG, "onCancelLoad: mTask=" + mTask);
1769911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        if (mTask != null) {
177899ca3236d86e921e24acb5d8f43fc1e28428043George Mount            if (!mStarted) {
178899ca3236d86e921e24acb5d8f43fc1e28428043George Mount                mContentChanged = true;
179899ca3236d86e921e24acb5d8f43fc1e28428043George Mount            }
180247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            if (mCancellingTask != null) {
181247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                // There was a pending task already waiting for a previous
182247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                // one being canceled; just drop it.
183c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown                if (DEBUG) Log.v(TAG,
184540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn                        "cancelLoad: still waiting for cancelled task; dropping next");
185247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                if (mTask.waiting) {
186247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    mTask.waiting = false;
187247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    mHandler.removeCallbacks(mTask);
188247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                }
189247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                mTask = null;
190247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                return false;
191247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            } else if (mTask.waiting) {
192247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                // There is a task, but it is waiting for the time it should
193247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                // execute.  We can just toss it.
194c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown                if (DEBUG) Log.v(TAG, "cancelLoad: task is waiting, dropping it");
195247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                mTask.waiting = false;
196247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                mHandler.removeCallbacks(mTask);
197247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                mTask = null;
198247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                return false;
199247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            } else {
200247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                boolean cancelled = mTask.cancel(false);
201c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown                if (DEBUG) Log.v(TAG, "cancelLoad: cancelled=" + cancelled);
202247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                if (cancelled) {
203247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    mCancellingTask = mTask;
204b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown                    cancelLoadInBackground();
205247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                }
206247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                mTask = null;
207247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                return cancelled;
208247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            }
2099911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        }
2109911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        return false;
2119911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton    }
212bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov
213bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov    /**
214bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov     * Called if the task was canceled before it was completed.  Gives the class a chance
215b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * to clean up post-cancellation and to properly dispose of the result.
216b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     *
217b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * @param data The value that was returned by {@link #loadInBackground}, or null
218b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * if the task threw {@link OperationCanceledException}.
219bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov     */
220327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn    public void onCanceled(D data) {
221327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn    }
2224afde4fda383116a9730aea1e931d4bce7ea0fd0Dmitri Plotnikov
223247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    void executePendingTask() {
224247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        if (mCancellingTask == null && mTask != null) {
225247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            if (mTask.waiting) {
226247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                mTask.waiting = false;
227247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                mHandler.removeCallbacks(mTask);
228247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            }
229247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            if (mUpdateThrottle > 0) {
230247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                long now = SystemClock.uptimeMillis();
231247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                if (now < (mLastLoadCompleteTime+mUpdateThrottle)) {
232247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    // Not yet time to do another load.
233c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown                    if (DEBUG) Log.v(TAG, "Waiting until "
234540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn                            + (mLastLoadCompleteTime+mUpdateThrottle)
235540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn                            + " to execute: " + mTask);
236247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    mTask.waiting = true;
237247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    mHandler.postAtTime(mTask, mLastLoadCompleteTime+mUpdateThrottle);
238247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    return;
239247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                }
240247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            }
241c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown            if (DEBUG) Log.v(TAG, "Executing: " + mTask);
242d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey            mTask.executeOnExecutor(mExecutor, (Void[]) null);
243247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        }
244247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    }
245247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn
246247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    void dispatchOnCancelled(LoadTask task, D data) {
247327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn        onCanceled(data);
248247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        if (mCancellingTask == task) {
249c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown            if (DEBUG) Log.v(TAG, "Cancelled task is now canceled!");
250ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn            rollbackContentChanged();
251247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            mLastLoadCompleteTime = SystemClock.uptimeMillis();
252247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            mCancellingTask = null;
253c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown            if (DEBUG) Log.v(TAG, "Delivering cancellation");
254b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown            deliverCancellation();
255247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            executePendingTask();
256247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        }
257247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    }
258247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn
2590e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn    void dispatchOnLoadComplete(LoadTask task, D data) {
2600e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn        if (mTask != task) {
261c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown            if (DEBUG) Log.v(TAG, "Load complete of old task, trying to cancel");
262247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            dispatchOnCancelled(task, data);
2630e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn        } else {
264260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn            if (isAbandoned()) {
265260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn                // This cursor has been abandoned; just cancel the new data.
266260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn                onCanceled(data);
267260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn            } else {
268ca614f78bed7eebf9dbfd77ba5720a0b5eeed816Dianne Hackborn                commitContentChanged();
269260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn                mLastLoadCompleteTime = SystemClock.uptimeMillis();
270260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn                mTask = null;
271c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown                if (DEBUG) Log.v(TAG, "Delivering result");
272260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn                deliverResult(data);
273260c3c77d9b340164e055f87002c64d78da6e836Dianne Hackborn            }
2740e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn        }
2759911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton    }
2769911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton
2779911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton    /**
278b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * Called on a worker thread to perform the actual load and to return
279b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * the result of the load operation.
280b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     *
281b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * Implementations should not deliver the result directly, but should return them
282b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * from this method, which will eventually end up calling {@link #deliverResult} on
283b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * the UI thread.  If implementations need to process the results on the UI thread
284b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * they may override {@link #deliverResult} and do so there.
285b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     *
286b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * To support cancellation, this method should periodically check the value of
287b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * {@link #isLoadInBackgroundCanceled} and terminate when it returns true.
288b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * Subclasses may also override {@link #cancelLoadInBackground} to interrupt the load
289b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * directly instead of polling {@link #isLoadInBackgroundCanceled}.
290b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     *
291b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * When the load is canceled, this method may either return normally or throw
292b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * {@link OperationCanceledException}.  In either case, the {@link Loader} will
293b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * call {@link #onCanceled} to perform post-cancellation cleanup and to dispose of the
294b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * result object, if any.
295b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     *
296b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * @return The result of the load operation.
297b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     *
298b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * @throws OperationCanceledException if the load is canceled during execution.
299b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     *
300b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * @see #isLoadInBackgroundCanceled
301b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * @see #cancelLoadInBackground
302b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * @see #onCanceled
303247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     */
304247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    public abstract D loadInBackground();
305247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn
306247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    /**
307b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * Calls {@link #loadInBackground()}.
308b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     *
309b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * This method is reserved for use by the loader framework.
310b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * Subclasses should override {@link #loadInBackground} instead of this method.
311b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     *
312b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * @return The result of the load operation.
3139911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton     *
314b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * @throws OperationCanceledException if the load is canceled during execution.
315b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     *
316b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * @see #loadInBackground
3179911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton     */
318247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    protected D onLoadInBackground() {
319247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        return loadInBackground();
320247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    }
321cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov
322cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov    /**
323b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * Called on the main thread to abort a load in progress.
324b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     *
325b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * Override this method to abort the current invocation of {@link #loadInBackground}
326b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * that is running in the background on a worker thread.
32775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     *
328b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * This method should do nothing if {@link #loadInBackground} has not started
329b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * running or if it has already finished.
330b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     *
331b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * @see #loadInBackground
33275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     */
333b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown    public void cancelLoadInBackground() {
33475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown    }
33575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown
33675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown    /**
337b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * Returns true if the current invocation of {@link #loadInBackground} is being canceled.
338b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     *
339b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * @return True if the current invocation of {@link #loadInBackground} is being canceled.
34075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     *
341b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown     * @see #loadInBackground
34275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     */
343b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown    public boolean isLoadInBackgroundCanceled() {
34475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown        return mCancellingTask != null;
34575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown    }
34675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown
34775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown    /**
348cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov     * Locks the current thread until the loader completes the current load
349cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov     * operation. Returns immediately if there is no load operation running.
35059d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov     * Should not be called from the UI thread: calling it from the UI
35159d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov     * thread would cause a deadlock.
352cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov     * <p>
353247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * Use for testing only.  <b>Never</b> call this from a UI thread.
3544afde4fda383116a9730aea1e931d4bce7ea0fd0Dmitri Plotnikov     *
3554afde4fda383116a9730aea1e931d4bce7ea0fd0Dmitri Plotnikov     * @hide
356cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov     */
357cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov    public void waitForLoader() {
358cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov        LoadTask task = mTask;
359cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov        if (task != null) {
360b19a71a20adb48c084e87d06a1e6b0dcb49170f5Jeff Brown            task.waitForLoader();
361cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov        }
362cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov    }
363247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn
364247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    @Override
365247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
366247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        super.dump(prefix, fd, writer, args);
367247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        if (mTask != null) {
368247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            writer.print(prefix); writer.print("mTask="); writer.print(mTask);
369247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    writer.print(" waiting="); writer.println(mTask.waiting);
370247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        }
371247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        if (mCancellingTask != null) {
372247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            writer.print(prefix); writer.print("mCancellingTask="); writer.print(mCancellingTask);
373247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    writer.print(" waiting="); writer.println(mCancellingTask.waiting);
374247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        }
375247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        if (mUpdateThrottle != 0) {
376247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            writer.print(prefix); writer.print("mUpdateThrottle=");
377247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    TimeUtils.formatDuration(mUpdateThrottle, writer);
378247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    writer.print(" mLastLoadCompleteTime=");
379247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    TimeUtils.formatDuration(mLastLoadCompleteTime,
380247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                            SystemClock.uptimeMillis(), writer);
381247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    writer.println();
382247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        }
383247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    }
3849911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton}
385