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