AsyncTaskLoader.java revision 327fbd2c8fa294b919475feb4c74a74ee1981e02
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;
21247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackbornimport android.os.SystemClock;
22540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackbornimport android.util.Slog;
23247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackbornimport android.util.TimeUtils;
24cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov
25247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackbornimport java.io.FileDescriptor;
26247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackbornimport java.io.PrintWriter;
2759d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikovimport java.util.concurrent.CountDownLatch;
289911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton
299911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton/**
309911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * Abstract Loader that provides an {@link AsyncTask} to do the work.
31bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov *
329911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton * @param <D> the data type to be loaded.
339911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton */
349911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamiltonpublic abstract class AsyncTaskLoader<D> extends Loader<D> {
35540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn    static final String TAG = "AsyncTaskLoader";
36540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn    static final boolean DEBUG = false;
37cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov
38247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    final class LoadTask extends AsyncTask<Void, Void, D> implements Runnable {
39bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov
40247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        D result;
41247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        boolean waiting;
42bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov
4359d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov        private CountDownLatch done = new CountDownLatch(1);
4459d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov
459911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        /* Runs on a worker thread */
469911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        @Override
479911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        protected D doInBackground(Void... params) {
48540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn            if (DEBUG) Slog.v(TAG, this + " >>> doInBackground");
49247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            result = AsyncTaskLoader.this.onLoadInBackground();
50540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn            if (DEBUG) Slog.v(TAG, this + "  <<< doInBackground");
51bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov            return result;
529911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        }
539911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton
549911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        /* Runs on the UI thread */
559911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        @Override
569911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        protected void onPostExecute(D data) {
57540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn            if (DEBUG) Slog.v(TAG, this + " onPostExecute");
5859d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov            try {
5959d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov                AsyncTaskLoader.this.dispatchOnLoadComplete(this, data);
6059d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov            } finally {
6159d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov                done.countDown();
6259d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov            }
639911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        }
64bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov
65bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov        @Override
66bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov        protected void onCancelled() {
67540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn            if (DEBUG) Slog.v(TAG, this + " onCancelled");
6859d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov            try {
6959d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov                AsyncTaskLoader.this.dispatchOnCancelled(this, result);
7059d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov            } finally {
7159d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov                done.countDown();
7259d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov            }
73247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        }
74247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn
75247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        @Override
76247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        public void run() {
77247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            waiting = false;
78247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            AsyncTaskLoader.this.executePendingTask();
79bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov        }
809911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton    }
819911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton
82cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov    volatile LoadTask mTask;
83247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    volatile LoadTask mCancellingTask;
84247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn
85247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    long mUpdateThrottle;
86247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    long mLastLoadCompleteTime = -10000;
87247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    Handler mHandler;
889911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton
899911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton    public AsyncTaskLoader(Context context) {
909911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        super(context);
919911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton    }
929911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton
93247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    /**
94247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * Set amount to throttle updates by.  This is the minimum time from
95247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * when the last {@link #onLoadInBackground()} call has completed until
96247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * a new load is scheduled.
97247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     *
98247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * @param delayMS Amount of delay, in milliseconds.
99247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     */
100247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    public void setUpdateThrottle(long delayMS) {
101247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        mUpdateThrottle = delayMS;
102247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        if (delayMS != 0) {
103247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            mHandler = new Handler();
104247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        }
105247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    }
106247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn
1079911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton    @Override
108a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn    protected void onForceLoad() {
1090e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn        super.onForceLoad();
110bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov        cancelLoad();
1119911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        mTask = new LoadTask();
112540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn        if (DEBUG) Slog.v(TAG, "Preparing load: mTask=" + mTask);
113247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        executePendingTask();
1149911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton    }
1159911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton
1169911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton    /**
1179911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton     * Attempt to cancel the current load task. See {@link AsyncTask#cancel(boolean)}
118247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * for more info.  Must be called on the main thread of the process.
119247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     *
120247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * <p>Cancelling is not an immediate operation, since the load is performed
121247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * in a background thread.  If there is currently a load in progress, this
122247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * method requests that the load be cancelled, and notes this is the case;
123247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * once the background thread has completed its work its remaining state
124247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * will be cleared.  If another load request comes in during this time,
125247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * it will be held until the cancelled load is complete.
1269911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton     *
127247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * @return Returns <tt>false</tt> if the task could not be cancelled,
1289911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton     *         typically because it has already completed normally, or
129247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     *         because {@link #startLoading()} hasn't been called; returns
130247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     *         <tt>true</tt> otherwise.
1319911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton     */
1329911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton    public boolean cancelLoad() {
133540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn        if (DEBUG) Slog.v(TAG, "cancelLoad: mTask=" + mTask);
1349911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        if (mTask != null) {
135247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            if (mCancellingTask != null) {
136247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                // There was a pending task already waiting for a previous
137247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                // one being canceled; just drop it.
138540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn                if (DEBUG) Slog.v(TAG,
139540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn                        "cancelLoad: still waiting for cancelled task; dropping next");
140247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                if (mTask.waiting) {
141247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    mTask.waiting = false;
142247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    mHandler.removeCallbacks(mTask);
143247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                }
144247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                mTask = null;
145247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                return false;
146247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            } else if (mTask.waiting) {
147247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                // There is a task, but it is waiting for the time it should
148247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                // execute.  We can just toss it.
149540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn                if (DEBUG) Slog.v(TAG, "cancelLoad: task is waiting, dropping it");
150247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                mTask.waiting = false;
151247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                mHandler.removeCallbacks(mTask);
152247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                mTask = null;
153247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                return false;
154247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            } else {
155247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                boolean cancelled = mTask.cancel(false);
156540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn                if (DEBUG) Slog.v(TAG, "cancelLoad: cancelled=" + cancelled);
157247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                if (cancelled) {
158247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    mCancellingTask = mTask;
159247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                }
160247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                mTask = null;
161247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                return cancelled;
162247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            }
1639911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        }
1649911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton        return false;
1659911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton    }
166bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov
167bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov    /**
168bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov     * Called if the task was canceled before it was completed.  Gives the class a chance
169bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov     * to properly dispose of the result.
170bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov     */
171327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn    public void onCanceled(D data) {
172327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn        onCancelled(data);
173bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov    }
174bef9c7a59dc020c5cdcbd555b5212ae5a10e8045Dmitri Plotnikov
175327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn    @Deprecated
176327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn    public void onCancelled(D data) {
177327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn    }
178327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn
179247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    void executePendingTask() {
180247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        if (mCancellingTask == null && mTask != null) {
181247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            if (mTask.waiting) {
182247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                mTask.waiting = false;
183247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                mHandler.removeCallbacks(mTask);
184247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            }
185247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            if (mUpdateThrottle > 0) {
186247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                long now = SystemClock.uptimeMillis();
187247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                if (now < (mLastLoadCompleteTime+mUpdateThrottle)) {
188247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    // Not yet time to do another load.
189540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn                    if (DEBUG) Slog.v(TAG, "Waiting until "
190540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn                            + (mLastLoadCompleteTime+mUpdateThrottle)
191540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn                            + " to execute: " + mTask);
192247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    mTask.waiting = true;
193247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    mHandler.postAtTime(mTask, mLastLoadCompleteTime+mUpdateThrottle);
194247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    return;
195247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                }
196247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            }
197540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn            if (DEBUG) Slog.v(TAG, "Executing: " + mTask);
198247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            mTask.execute((Void[]) null);
199247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        }
200247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    }
201247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn
202247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    void dispatchOnCancelled(LoadTask task, D data) {
203327fbd2c8fa294b919475feb4c74a74ee1981e02Dianne Hackborn        onCanceled(data);
204247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        if (mCancellingTask == task) {
205540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn            if (DEBUG) Slog.v(TAG, "Cancelled task is now canceled!");
206247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            mLastLoadCompleteTime = SystemClock.uptimeMillis();
207247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            mCancellingTask = null;
208247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            executePendingTask();
209247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        }
210247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    }
211247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn
2120e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn    void dispatchOnLoadComplete(LoadTask task, D data) {
2130e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn        if (mTask != task) {
214540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn            if (DEBUG) Slog.v(TAG, "Load complete of old task, trying to cancel");
215247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            dispatchOnCancelled(task, data);
2160e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn        } else {
217247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            mLastLoadCompleteTime = SystemClock.uptimeMillis();
2180e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn            mTask = null;
219540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn            if (DEBUG) Slog.v(TAG, "Delivering result");
2200e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn            deliverResult(data);
2210e3b8f421dfcc5363f234eb1b76479cb2fb2e8eeDianne Hackborn        }
2229911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton    }
2239911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton
2249911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton    /**
225247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     */
226247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    public abstract D loadInBackground();
227247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn
228247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    /**
2299911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton     * Called on a worker thread to perform the actual load. Implementations should not deliver the
230247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * result directly, but should return them from this method, which will eventually end up
231247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * calling {@link #deliverResult} on the UI thread. If implementations need to process
232247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * the results on the UI thread they may override {@link #deliverResult} and do so
233e6c6d09a7eb9a7cd6e94c164e75a08dc499fd577Jeff Hamilton     * there.
2349911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton     *
235247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * @return Implementations must return the result of their load operation.
2369911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton     */
237247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    protected D onLoadInBackground() {
238247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        return loadInBackground();
239247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    }
240cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov
241cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov    /**
242cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov     * Locks the current thread until the loader completes the current load
243cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov     * operation. Returns immediately if there is no load operation running.
24459d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov     * Should not be called from the UI thread: calling it from the UI
24559d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov     * thread would cause a deadlock.
246cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov     * <p>
247247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn     * Use for testing only.  <b>Never</b> call this from a UI thread.
248cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov     */
249cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov    public void waitForLoader() {
250cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov        LoadTask task = mTask;
251cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov        if (task != null) {
252cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov            try {
25359d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov                task.done.await();
254cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov            } catch (InterruptedException e) {
25559d8edd09dc88cc0eb629bdee711a004d300f2faDmitri Plotnikov                // Ignore
256cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov            }
257cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov        }
258cd3676e7b835653b04d4f66251a63749e7603f5bDmitri Plotnikov    }
259247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn
260247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    @Override
261247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
262247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        super.dump(prefix, fd, writer, args);
263247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        if (mTask != null) {
264247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            writer.print(prefix); writer.print("mTask="); writer.print(mTask);
265247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    writer.print(" waiting="); writer.println(mTask.waiting);
266247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        }
267247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        if (mCancellingTask != null) {
268247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            writer.print(prefix); writer.print("mCancellingTask="); writer.print(mCancellingTask);
269247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    writer.print(" waiting="); writer.println(mCancellingTask.waiting);
270247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        }
271247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        if (mUpdateThrottle != 0) {
272247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn            writer.print(prefix); writer.print("mUpdateThrottle=");
273247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    TimeUtils.formatDuration(mUpdateThrottle, writer);
274247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    writer.print(" mLastLoadCompleteTime=");
275247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    TimeUtils.formatDuration(mLastLoadCompleteTime,
276247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                            SystemClock.uptimeMillis(), writer);
277247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                    writer.println();
278247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        }
279247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    }
2809911b7f83db2e960f72345e6d50df2b77ca75e3fJeff Hamilton}
281