1cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn/*
2cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Copyright (C) 2011 The Android Open Source Project
3cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *
4cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
5cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * you may not use this file except in compliance with the License.
6cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * You may obtain a copy of the License at
7cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *
8cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
9cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *
10cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
11cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
12cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * See the License for the specific language governing permissions and
14cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * limitations under the License.
15cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn */
16cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
17cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornpackage android.support.v4.content;
18cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
19cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.content.Context;
20cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.os.Handler;
21cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.os.SystemClock;
22cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.support.v4.util.TimeUtils;
23cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.util.Log;
24cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
25cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport java.io.FileDescriptor;
26cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport java.io.PrintWriter;
27cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport java.util.concurrent.CountDownLatch;
28cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
29cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn/**
30cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Static library support version of the framework's {@link android.content.AsyncTaskLoader}.
31cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Used to write apps that run on platforms prior to Android 3.0.  When running
32cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * on Android 3.0 or above, this implementation is still used; it does not try
33cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * to switch to the framework's implementation.  See the framework SDK
34cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * documentation for a class overview.
35cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn */
36cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornpublic abstract class AsyncTaskLoader<D> extends Loader<D> {
37cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    static final String TAG = "AsyncTaskLoader";
38cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    static final boolean DEBUG = false;
39cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
40fbabff99ccbcb576c713991c5db5dec21a0d0ce0Dianne Hackborn    final class LoadTask extends ModernAsyncTask<Void, Void, D> implements Runnable {
41cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
42cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        D result;
43cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        boolean waiting;
44cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
45cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        private CountDownLatch done = new CountDownLatch(1);
46cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
47cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        /* Runs on a worker thread */
48cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        @Override
49cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        protected D doInBackground(Void... params) {
50cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (DEBUG) Log.v(TAG, this + " >>> doInBackground");
51cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            result = AsyncTaskLoader.this.onLoadInBackground();
52cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (DEBUG) Log.v(TAG, this + "  <<< doInBackground");
53cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            return result;
54cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
55cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
56cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        /* Runs on the UI thread */
57cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        @Override
58cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        protected void onPostExecute(D data) {
59cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (DEBUG) Log.v(TAG, this + " onPostExecute");
60cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            try {
61cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                AsyncTaskLoader.this.dispatchOnLoadComplete(this, data);
62cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            } finally {
63cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                done.countDown();
64cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
65cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
66cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
67cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        @Override
68cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        protected void onCancelled() {
69cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (DEBUG) Log.v(TAG, this + " onCancelled");
70cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            try {
71cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                AsyncTaskLoader.this.dispatchOnCancelled(this, result);
72cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            } finally {
73cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                done.countDown();
74cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
75cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
76cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
77cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        @Override
78cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        public void run() {
79cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            waiting = false;
80cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            AsyncTaskLoader.this.executePendingTask();
81cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
82cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
83cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
84cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    volatile LoadTask mTask;
85cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    volatile LoadTask mCancellingTask;
86cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
87cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    long mUpdateThrottle;
88cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    long mLastLoadCompleteTime = -10000;
89cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    Handler mHandler;
90cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
91cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public AsyncTaskLoader(Context context) {
92cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        super(context);
93cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
94cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
95cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
96cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Set amount to throttle updates by.  This is the minimum time from
97cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * when the last {@link #onLoadInBackground()} call has completed until
98cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * a new load is scheduled.
99cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
100cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param delayMS Amount of delay, in milliseconds.
101cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
102cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void setUpdateThrottle(long delayMS) {
103cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mUpdateThrottle = delayMS;
104cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (delayMS != 0) {
105cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mHandler = new Handler();
106cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
107cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
108cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
109cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    @Override
110cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    protected void onForceLoad() {
111cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        super.onForceLoad();
112cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        cancelLoad();
113cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mTask = new LoadTask();
114cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (DEBUG) Log.v(TAG, "Preparing load: mTask=" + mTask);
115cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        executePendingTask();
116cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
117cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
118cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
1190574ca37da4619afe4e26753f5a1b4de314b6565Svetoslav Ganov     * Attempt to cancel the current load task. See {@link android.os.AsyncTask#cancel(boolean)}
120cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * for more info.  Must be called on the main thread of the process.
121cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
122cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * <p>Cancelling is not an immediate operation, since the load is performed
123cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * in a background thread.  If there is currently a load in progress, this
124cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * method requests that the load be cancelled, and notes this is the case;
125cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * once the background thread has completed its work its remaining state
126cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * will be cleared.  If another load request comes in during this time,
127cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * it will be held until the cancelled load is complete.
128cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
129cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @return Returns <tt>false</tt> if the task could not be cancelled,
130cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *         typically because it has already completed normally, or
131cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *         because {@link #startLoading()} hasn't been called; returns
132cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *         <tt>true</tt> otherwise.
133cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
134cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public boolean cancelLoad() {
135cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (DEBUG) Log.v(TAG, "cancelLoad: mTask=" + mTask);
136cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mTask != null) {
137cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mCancellingTask != null) {
138cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // There was a pending task already waiting for a previous
139cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // one being canceled; just drop it.
140cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (DEBUG) Log.v(TAG,
141cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        "cancelLoad: still waiting for cancelled task; dropping next");
142cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (mTask.waiting) {
143cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    mTask.waiting = false;
144cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    mHandler.removeCallbacks(mTask);
145cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                }
146cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mTask = null;
147cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                return false;
148cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            } else if (mTask.waiting) {
149cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // There is a task, but it is waiting for the time it should
150cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // execute.  We can just toss it.
151cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (DEBUG) Log.v(TAG, "cancelLoad: task is waiting, dropping it");
152cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mTask.waiting = false;
153cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mHandler.removeCallbacks(mTask);
154cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mTask = null;
155cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                return false;
156cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            } else {
157cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                boolean cancelled = mTask.cancel(false);
158cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (DEBUG) Log.v(TAG, "cancelLoad: cancelled=" + cancelled);
159cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (cancelled) {
160cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    mCancellingTask = mTask;
161cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                }
162cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mTask = null;
163cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                return cancelled;
164cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
165cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
166cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return false;
167cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
168cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
169cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
170cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Called if the task was canceled before it was completed.  Gives the class a chance
171cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * to properly dispose of the result.
172cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
173cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void onCanceled(D data) {
174cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
175cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
176cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    void executePendingTask() {
177cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mCancellingTask == null && mTask != null) {
178cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mTask.waiting) {
179cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mTask.waiting = false;
180cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mHandler.removeCallbacks(mTask);
181cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
182cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mUpdateThrottle > 0) {
183cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                long now = SystemClock.uptimeMillis();
184cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (now < (mLastLoadCompleteTime+mUpdateThrottle)) {
185cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    // Not yet time to do another load.
186cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    if (DEBUG) Log.v(TAG, "Waiting until "
187cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                            + (mLastLoadCompleteTime+mUpdateThrottle)
188cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                            + " to execute: " + mTask);
189cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    mTask.waiting = true;
190cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    mHandler.postAtTime(mTask, mLastLoadCompleteTime+mUpdateThrottle);
191cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    return;
192cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                }
193cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
194cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (DEBUG) Log.v(TAG, "Executing: " + mTask);
195fbabff99ccbcb576c713991c5db5dec21a0d0ce0Dianne Hackborn            mTask.executeOnExecutor(ModernAsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
196cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
197cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
198cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
199cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    void dispatchOnCancelled(LoadTask task, D data) {
200cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        onCanceled(data);
201cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mCancellingTask == task) {
202cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (DEBUG) Log.v(TAG, "Cancelled task is now canceled!");
20380a0a3a33e3f6c27da4681a4f02eb2c6aae1fd40Dianne Hackborn            rollbackContentChanged();
204cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mLastLoadCompleteTime = SystemClock.uptimeMillis();
205cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mCancellingTask = null;
206cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            executePendingTask();
207cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
208cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
209cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
210cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    void dispatchOnLoadComplete(LoadTask task, D data) {
211cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mTask != task) {
212cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (DEBUG) Log.v(TAG, "Load complete of old task, trying to cancel");
213cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            dispatchOnCancelled(task, data);
214cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        } else {
215cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (isAbandoned()) {
216cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // This cursor has been abandoned; just cancel the new data.
217cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                onCanceled(data);
218cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            } else {
21980a0a3a33e3f6c27da4681a4f02eb2c6aae1fd40Dianne Hackborn                commitContentChanged();
220cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mLastLoadCompleteTime = SystemClock.uptimeMillis();
221cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mTask = null;
222cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (DEBUG) Log.v(TAG, "Delivering result");
223cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                deliverResult(data);
224cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
225cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
226cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
227cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
228cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
229cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
230cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public abstract D loadInBackground();
231cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
232cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
233cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Called on a worker thread to perform the actual load. Implementations should not deliver the
234cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * result directly, but should return them from this method, which will eventually end up
235cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * calling {@link #deliverResult} on the UI thread. If implementations need to process
236cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * the results on the UI thread they may override {@link #deliverResult} and do so
237cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * there.
238cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
239cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @return Implementations must return the result of their load operation.
240cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
241cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    protected D onLoadInBackground() {
242cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return loadInBackground();
243cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
244cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
245cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
246cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Locks the current thread until the loader completes the current load
247cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * operation. Returns immediately if there is no load operation running.
248cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Should not be called from the UI thread: calling it from the UI
249cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * thread would cause a deadlock.
250cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * <p>
251cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Use for testing only.  <b>Never</b> call this from a UI thread.
252cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
253cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @hide
254cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
255cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void waitForLoader() {
256cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        LoadTask task = mTask;
257cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (task != null) {
258cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            try {
259cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                task.done.await();
260cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            } catch (InterruptedException e) {
261cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // Ignore
262cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
263cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
264cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
265cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
266cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    @Override
267cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
268cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        super.dump(prefix, fd, writer, args);
269cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mTask != null) {
270cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            writer.print(prefix); writer.print("mTask="); writer.print(mTask);
271cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    writer.print(" waiting="); writer.println(mTask.waiting);
272cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
273cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mCancellingTask != null) {
274cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            writer.print(prefix); writer.print("mCancellingTask="); writer.print(mCancellingTask);
275cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    writer.print(" waiting="); writer.println(mCancellingTask.waiting);
276cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
277cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mUpdateThrottle != 0) {
278cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            writer.print(prefix); writer.print("mUpdateThrottle=");
279cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    TimeUtils.formatDuration(mUpdateThrottle, writer);
280cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    writer.print(" mLastLoadCompleteTime=");
281cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    TimeUtils.formatDuration(mLastLoadCompleteTime,
282cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                            SystemClock.uptimeMillis(), writer);
283cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    writer.println();
284cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
285cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
286cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn}
287