Home | History | Annotate | Download | only in os
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.os;
     18 
     19 import android.annotation.MainThread;
     20 import android.annotation.Nullable;
     21 import android.annotation.UnsupportedAppUsage;
     22 import android.annotation.WorkerThread;
     23 
     24 import java.util.ArrayDeque;
     25 import java.util.concurrent.Callable;
     26 import java.util.concurrent.CancellationException;
     27 import java.util.concurrent.ExecutionException;
     28 import java.util.concurrent.Executor;
     29 import java.util.concurrent.FutureTask;
     30 import java.util.concurrent.LinkedBlockingQueue;
     31 import java.util.concurrent.RejectedExecutionHandler;
     32 import java.util.concurrent.SynchronousQueue;
     33 import java.util.concurrent.ThreadFactory;
     34 import java.util.concurrent.ThreadPoolExecutor;
     35 import java.util.concurrent.TimeUnit;
     36 import java.util.concurrent.TimeoutException;
     37 import java.util.concurrent.atomic.AtomicBoolean;
     38 import java.util.concurrent.atomic.AtomicInteger;
     39 
     40 /**
     41  * <p>AsyncTask enables proper and easy use of the UI thread. This class allows you
     42  * to perform background operations and publish results on the UI thread without
     43  * having to manipulate threads and/or handlers.</p>
     44  *
     45  * <p>AsyncTask is designed to be a helper class around {@link Thread} and {@link Handler}
     46  * and does not constitute a generic threading framework. AsyncTasks should ideally be
     47  * used for short operations (a few seconds at the most.) If you need to keep threads
     48  * running for long periods of time, it is highly recommended you use the various APIs
     49  * provided by the <code>java.util.concurrent</code> package such as {@link Executor},
     50  * {@link ThreadPoolExecutor} and {@link FutureTask}.</p>
     51  *
     52  * <p>An asynchronous task is defined by a computation that runs on a background thread and
     53  * whose result is published on the UI thread. An asynchronous task is defined by 3 generic
     54  * types, called <code>Params</code>, <code>Progress</code> and <code>Result</code>,
     55  * and 4 steps, called <code>onPreExecute</code>, <code>doInBackground</code>,
     56  * <code>onProgressUpdate</code> and <code>onPostExecute</code>.</p>
     57  *
     58  * <div class="special reference">
     59  * <h3>Developer Guides</h3>
     60  * <p>For more information about using tasks and threads, read the
     61  * <a href="{@docRoot}guide/components/processes-and-threads.html">Processes and
     62  * Threads</a> developer guide.</p>
     63  * </div>
     64  *
     65  * <h2>Usage</h2>
     66  * <p>AsyncTask must be subclassed to be used. The subclass will override at least
     67  * one method ({@link #doInBackground}), and most often will override a
     68  * second one ({@link #onPostExecute}.)</p>
     69  *
     70  * <p>Here is an example of subclassing:</p>
     71  * <pre class="prettyprint">
     72  * private class DownloadFilesTask extends AsyncTask&lt;URL, Integer, Long&gt; {
     73  *     protected Long doInBackground(URL... urls) {
     74  *         int count = urls.length;
     75  *         long totalSize = 0;
     76  *         for (int i = 0; i &lt; count; i++) {
     77  *             totalSize += Downloader.downloadFile(urls[i]);
     78  *             publishProgress((int) ((i / (float) count) * 100));
     79  *             // Escape early if cancel() is called
     80  *             if (isCancelled()) break;
     81  *         }
     82  *         return totalSize;
     83  *     }
     84  *
     85  *     protected void onProgressUpdate(Integer... progress) {
     86  *         setProgressPercent(progress[0]);
     87  *     }
     88  *
     89  *     protected void onPostExecute(Long result) {
     90  *         showDialog("Downloaded " + result + " bytes");
     91  *     }
     92  * }
     93  * </pre>
     94  *
     95  * <p>Once created, a task is executed very simply:</p>
     96  * <pre class="prettyprint">
     97  * new DownloadFilesTask().execute(url1, url2, url3);
     98  * </pre>
     99  *
    100  * <h2>AsyncTask's generic types</h2>
    101  * <p>The three types used by an asynchronous task are the following:</p>
    102  * <ol>
    103  *     <li><code>Params</code>, the type of the parameters sent to the task upon
    104  *     execution.</li>
    105  *     <li><code>Progress</code>, the type of the progress units published during
    106  *     the background computation.</li>
    107  *     <li><code>Result</code>, the type of the result of the background
    108  *     computation.</li>
    109  * </ol>
    110  * <p>Not all types are always used by an asynchronous task. To mark a type as unused,
    111  * simply use the type {@link Void}:</p>
    112  * <pre>
    113  * private class MyTask extends AsyncTask&lt;Void, Void, Void&gt; { ... }
    114  * </pre>
    115  *
    116  * <h2>The 4 steps</h2>
    117  * <p>When an asynchronous task is executed, the task goes through 4 steps:</p>
    118  * <ol>
    119  *     <li>{@link #onPreExecute()}, invoked on the UI thread before the task
    120  *     is executed. This step is normally used to setup the task, for instance by
    121  *     showing a progress bar in the user interface.</li>
    122  *     <li>{@link #doInBackground}, invoked on the background thread
    123  *     immediately after {@link #onPreExecute()} finishes executing. This step is used
    124  *     to perform background computation that can take a long time. The parameters
    125  *     of the asynchronous task are passed to this step. The result of the computation must
    126  *     be returned by this step and will be passed back to the last step. This step
    127  *     can also use {@link #publishProgress} to publish one or more units
    128  *     of progress. These values are published on the UI thread, in the
    129  *     {@link #onProgressUpdate} step.</li>
    130  *     <li>{@link #onProgressUpdate}, invoked on the UI thread after a
    131  *     call to {@link #publishProgress}. The timing of the execution is
    132  *     undefined. This method is used to display any form of progress in the user
    133  *     interface while the background computation is still executing. For instance,
    134  *     it can be used to animate a progress bar or show logs in a text field.</li>
    135  *     <li>{@link #onPostExecute}, invoked on the UI thread after the background
    136  *     computation finishes. The result of the background computation is passed to
    137  *     this step as a parameter.</li>
    138  * </ol>
    139  *
    140  * <h2>Cancelling a task</h2>
    141  * <p>A task can be cancelled at any time by invoking {@link #cancel(boolean)}. Invoking
    142  * this method will cause subsequent calls to {@link #isCancelled()} to return true.
    143  * After invoking this method, {@link #onCancelled(Object)}, instead of
    144  * {@link #onPostExecute(Object)} will be invoked after {@link #doInBackground(Object[])}
    145  * returns. To ensure that a task is cancelled as quickly as possible, you should always
    146  * check the return value of {@link #isCancelled()} periodically from
    147  * {@link #doInBackground(Object[])}, if possible (inside a loop for instance.)</p>
    148  *
    149  * <h2>Threading rules</h2>
    150  * <p>There are a few threading rules that must be followed for this class to
    151  * work properly:</p>
    152  * <ul>
    153  *     <li>The AsyncTask class must be loaded on the UI thread. This is done
    154  *     automatically as of {@link android.os.Build.VERSION_CODES#JELLY_BEAN}.</li>
    155  *     <li>The task instance must be created on the UI thread.</li>
    156  *     <li>{@link #execute} must be invoked on the UI thread.</li>
    157  *     <li>Do not call {@link #onPreExecute()}, {@link #onPostExecute},
    158  *     {@link #doInBackground}, {@link #onProgressUpdate} manually.</li>
    159  *     <li>The task can be executed only once (an exception will be thrown if
    160  *     a second execution is attempted.)</li>
    161  * </ul>
    162  *
    163  * <h2>Memory observability</h2>
    164  * <p>AsyncTask guarantees that all callback calls are synchronized to ensure the following
    165  * without explicit synchronizations.</p>
    166  * <ul>
    167  *     <li>The memory effects of {@link #onPreExecute}, and anything else
    168  *     executed before the call to {@link #execute}, including the construction
    169  *     of the AsyncTask object, are visible to {@link #doInBackground}.
    170  *     <li>The memory effects of {@link #doInBackground} are visible to
    171  *     {@link #onPostExecute}.
    172  *     <li>Any memory effects of {@link #doInBackground} preceding a call
    173  *     to {@link #publishProgress} are visible to the corresponding
    174  *     {@link #onProgressUpdate} call. (But {@link #doInBackground} continues to
    175  *     run, and care needs to be taken that later updates in {@link #doInBackground}
    176  *     do not interfere with an in-progress {@link #onProgressUpdate} call.)
    177  *     <li>Any memory effects preceding a call to {@link #cancel} are visible
    178  *     after a call to {@link #isCancelled} that returns true as a result, or
    179  *     during and after a resulting call to {@link #onCancelled}.
    180  * </ul>
    181  *
    182  * <h2>Order of execution</h2>
    183  * <p>When first introduced, AsyncTasks were executed serially on a single background
    184  * thread. Starting with {@link android.os.Build.VERSION_CODES#DONUT}, this was changed
    185  * to a pool of threads allowing multiple tasks to operate in parallel. Starting with
    186  * {@link android.os.Build.VERSION_CODES#HONEYCOMB}, tasks are executed on a single
    187  * thread to avoid common application errors caused by parallel execution.</p>
    188  * <p>If you truly want parallel execution, you can invoke
    189  * {@link #executeOnExecutor(java.util.concurrent.Executor, Object[])} with
    190  * {@link #THREAD_POOL_EXECUTOR}.</p>
    191  */
    192 public abstract class AsyncTask<Params, Progress, Result> {
    193     private static final String LOG_TAG = "AsyncTask";
    194 
    195     // We keep only a single pool thread around all the time.
    196     // We let the pool grow to a fairly large number of threads if necessary,
    197     // but let them time out quickly. In the unlikely case that we run out of threads,
    198     // we fall back to a simple unbounded-queue executor.
    199     // This combination ensures that:
    200     // 1. We normally keep few threads (1) around.
    201     // 2. We queue only after launching a significantly larger, but still bounded, set of threads.
    202     // 3. We keep the total number of threads bounded, but still allow an unbounded set
    203     //    of tasks to be queued.
    204     private static final int CORE_POOL_SIZE = 1;
    205     private static final int MAXIMUM_POOL_SIZE = 20;
    206     private static final int BACKUP_POOL_SIZE = 5;
    207     private static final int KEEP_ALIVE_SECONDS = 3;
    208 
    209     private static final ThreadFactory sThreadFactory = new ThreadFactory() {
    210         private final AtomicInteger mCount = new AtomicInteger(1);
    211 
    212         public Thread newThread(Runnable r) {
    213             return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
    214         }
    215     };
    216 
    217     // Used only for rejected executions.
    218     // Initialization protected by sRunOnSerialPolicy lock.
    219     private static ThreadPoolExecutor sBackupExecutor;
    220     private static LinkedBlockingQueue<Runnable> sBackupExecutorQueue;
    221 
    222     private static final RejectedExecutionHandler sRunOnSerialPolicy =
    223             new RejectedExecutionHandler() {
    224         public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    225             android.util.Log.w(LOG_TAG, "Exceeded ThreadPoolExecutor pool size");
    226             // As a last ditch fallback, run it on an executor with an unbounded queue.
    227             // Create this executor lazily, hopefully almost never.
    228             synchronized (this) {
    229                 if (sBackupExecutor == null) {
    230                     sBackupExecutorQueue = new LinkedBlockingQueue<Runnable>();
    231                     sBackupExecutor = new ThreadPoolExecutor(
    232                             BACKUP_POOL_SIZE, BACKUP_POOL_SIZE, KEEP_ALIVE_SECONDS,
    233                             TimeUnit.SECONDS, sBackupExecutorQueue, sThreadFactory);
    234                     sBackupExecutor.allowCoreThreadTimeOut(true);
    235                 }
    236             }
    237             sBackupExecutor.execute(r);
    238         }
    239     };
    240 
    241     /**
    242      * An {@link Executor} that can be used to execute tasks in parallel.
    243      */
    244     public static final Executor THREAD_POOL_EXECUTOR;
    245 
    246     static {
    247         ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
    248                 CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
    249                 new SynchronousQueue<Runnable>(), sThreadFactory);
    250         threadPoolExecutor.setRejectedExecutionHandler(sRunOnSerialPolicy);
    251         THREAD_POOL_EXECUTOR = threadPoolExecutor;
    252     }
    253 
    254     /**
    255      * An {@link Executor} that executes tasks one at a time in serial
    256      * order.  This serialization is global to a particular process.
    257      */
    258     public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
    259 
    260     private static final int MESSAGE_POST_RESULT = 0x1;
    261     private static final int MESSAGE_POST_PROGRESS = 0x2;
    262 
    263     @UnsupportedAppUsage
    264     private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
    265     private static InternalHandler sHandler;
    266 
    267     @UnsupportedAppUsage
    268     private final WorkerRunnable<Params, Result> mWorker;
    269     @UnsupportedAppUsage
    270     private final FutureTask<Result> mFuture;
    271 
    272     @UnsupportedAppUsage
    273     private volatile Status mStatus = Status.PENDING;
    274 
    275     private final AtomicBoolean mCancelled = new AtomicBoolean();
    276     @UnsupportedAppUsage
    277     private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
    278 
    279     private final Handler mHandler;
    280 
    281     private static class SerialExecutor implements Executor {
    282         final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
    283         Runnable mActive;
    284 
    285         public synchronized void execute(final Runnable r) {
    286             mTasks.offer(new Runnable() {
    287                 public void run() {
    288                     try {
    289                         r.run();
    290                     } finally {
    291                         scheduleNext();
    292                     }
    293                 }
    294             });
    295             if (mActive == null) {
    296                 scheduleNext();
    297             }
    298         }
    299 
    300         protected synchronized void scheduleNext() {
    301             if ((mActive = mTasks.poll()) != null) {
    302                 THREAD_POOL_EXECUTOR.execute(mActive);
    303             }
    304         }
    305     }
    306 
    307     /**
    308      * Indicates the current status of the task. Each status will be set only once
    309      * during the lifetime of a task.
    310      */
    311     public enum Status {
    312         /**
    313          * Indicates that the task has not been executed yet.
    314          */
    315         PENDING,
    316         /**
    317          * Indicates that the task is running.
    318          */
    319         RUNNING,
    320         /**
    321          * Indicates that {@link AsyncTask#onPostExecute} has finished.
    322          */
    323         FINISHED,
    324     }
    325 
    326     private static Handler getMainHandler() {
    327         synchronized (AsyncTask.class) {
    328             if (sHandler == null) {
    329                 sHandler = new InternalHandler(Looper.getMainLooper());
    330             }
    331             return sHandler;
    332         }
    333     }
    334 
    335     private Handler getHandler() {
    336         return mHandler;
    337     }
    338 
    339     /** @hide */
    340     @UnsupportedAppUsage
    341     public static void setDefaultExecutor(Executor exec) {
    342         sDefaultExecutor = exec;
    343     }
    344 
    345     /**
    346      * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
    347      */
    348     public AsyncTask() {
    349         this((Looper) null);
    350     }
    351 
    352     /**
    353      * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
    354      *
    355      * @hide
    356      */
    357     public AsyncTask(@Nullable Handler handler) {
    358         this(handler != null ? handler.getLooper() : null);
    359     }
    360 
    361     /**
    362      * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
    363      *
    364      * @hide
    365      */
    366     public AsyncTask(@Nullable Looper callbackLooper) {
    367         mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
    368             ? getMainHandler()
    369             : new Handler(callbackLooper);
    370 
    371         mWorker = new WorkerRunnable<Params, Result>() {
    372             public Result call() throws Exception {
    373                 mTaskInvoked.set(true);
    374                 Result result = null;
    375                 try {
    376                     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    377                     //noinspection unchecked
    378                     result = doInBackground(mParams);
    379                     Binder.flushPendingCommands();
    380                 } catch (Throwable tr) {
    381                     mCancelled.set(true);
    382                     throw tr;
    383                 } finally {
    384                     postResult(result);
    385                 }
    386                 return result;
    387             }
    388         };
    389 
    390         mFuture = new FutureTask<Result>(mWorker) {
    391             @Override
    392             protected void done() {
    393                 try {
    394                     postResultIfNotInvoked(get());
    395                 } catch (InterruptedException e) {
    396                     android.util.Log.w(LOG_TAG, e);
    397                 } catch (ExecutionException e) {
    398                     throw new RuntimeException("An error occurred while executing doInBackground()",
    399                             e.getCause());
    400                 } catch (CancellationException e) {
    401                     postResultIfNotInvoked(null);
    402                 }
    403             }
    404         };
    405     }
    406 
    407     private void postResultIfNotInvoked(Result result) {
    408         final boolean wasTaskInvoked = mTaskInvoked.get();
    409         if (!wasTaskInvoked) {
    410             postResult(result);
    411         }
    412     }
    413 
    414     private Result postResult(Result result) {
    415         @SuppressWarnings("unchecked")
    416         Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
    417                 new AsyncTaskResult<Result>(this, result));
    418         message.sendToTarget();
    419         return result;
    420     }
    421 
    422     /**
    423      * Returns the current status of this task.
    424      *
    425      * @return The current status.
    426      */
    427     public final Status getStatus() {
    428         return mStatus;
    429     }
    430 
    431     /**
    432      * Override this method to perform a computation on a background thread. The
    433      * specified parameters are the parameters passed to {@link #execute}
    434      * by the caller of this task.
    435      *
    436      * This will normally run on a background thread. But to better
    437      * support testing frameworks, it is recommended that this also tolerates
    438      * direct execution on the foreground thread, as part of the {@link #execute} call.
    439      *
    440      * This method can call {@link #publishProgress} to publish updates
    441      * on the UI thread.
    442      *
    443      * @param params The parameters of the task.
    444      *
    445      * @return A result, defined by the subclass of this task.
    446      *
    447      * @see #onPreExecute()
    448      * @see #onPostExecute
    449      * @see #publishProgress
    450      */
    451     @WorkerThread
    452     protected abstract Result doInBackground(Params... params);
    453 
    454     /**
    455      * Runs on the UI thread before {@link #doInBackground}.
    456      * Invoked directly by {@link #execute} or {@link #executeOnExecutor}.
    457      * The default version does nothing.
    458      *
    459      * @see #onPostExecute
    460      * @see #doInBackground
    461      */
    462     @MainThread
    463     protected void onPreExecute() {
    464     }
    465 
    466     /**
    467      * <p>Runs on the UI thread after {@link #doInBackground}. The
    468      * specified result is the value returned by {@link #doInBackground}.
    469      * To better support testing frameworks, it is recommended that this be
    470      * written to tolerate direct execution as part of the execute() call.
    471      * The default version does nothing.</p>
    472      *
    473      * <p>This method won't be invoked if the task was cancelled.</p>
    474      *
    475      * @param result The result of the operation computed by {@link #doInBackground}.
    476      *
    477      * @see #onPreExecute
    478      * @see #doInBackground
    479      * @see #onCancelled(Object)
    480      */
    481     @SuppressWarnings({"UnusedDeclaration"})
    482     @MainThread
    483     protected void onPostExecute(Result result) {
    484     }
    485 
    486     /**
    487      * Runs on the UI thread after {@link #publishProgress} is invoked.
    488      * The specified values are the values passed to {@link #publishProgress}.
    489      * The default version does nothing.
    490      *
    491      * @param values The values indicating progress.
    492      *
    493      * @see #publishProgress
    494      * @see #doInBackground
    495      */
    496     @SuppressWarnings({"UnusedDeclaration"})
    497     @MainThread
    498     protected void onProgressUpdate(Progress... values) {
    499     }
    500 
    501     /**
    502      * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and
    503      * {@link #doInBackground(Object[])} has finished.</p>
    504      *
    505      * <p>The default implementation simply invokes {@link #onCancelled()} and
    506      * ignores the result. If you write your own implementation, do not call
    507      * <code>super.onCancelled(result)</code>.</p>
    508      *
    509      * @param result The result, if any, computed in
    510      *               {@link #doInBackground(Object[])}, can be null
    511      *
    512      * @see #cancel(boolean)
    513      * @see #isCancelled()
    514      */
    515     @SuppressWarnings({"UnusedParameters"})
    516     @MainThread
    517     protected void onCancelled(Result result) {
    518         onCancelled();
    519     }
    520 
    521     /**
    522      * <p>Applications should preferably override {@link #onCancelled(Object)}.
    523      * This method is invoked by the default implementation of
    524      * {@link #onCancelled(Object)}.
    525      * The default version does nothing.</p>
    526      *
    527      * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and
    528      * {@link #doInBackground(Object[])} has finished.</p>
    529      *
    530      * @see #onCancelled(Object)
    531      * @see #cancel(boolean)
    532      * @see #isCancelled()
    533      */
    534     @MainThread
    535     protected void onCancelled() {
    536     }
    537 
    538     /**
    539      * Returns <tt>true</tt> if this task was cancelled before it completed
    540      * normally. If you are calling {@link #cancel(boolean)} on the task,
    541      * the value returned by this method should be checked periodically from
    542      * {@link #doInBackground(Object[])} to end the task as soon as possible.
    543      *
    544      * @return <tt>true</tt> if task was cancelled before it completed
    545      *
    546      * @see #cancel(boolean)
    547      */
    548     public final boolean isCancelled() {
    549         return mCancelled.get();
    550     }
    551 
    552     /**
    553      * <p>Attempts to cancel execution of this task.  This attempt will
    554      * fail if the task has already completed, already been cancelled,
    555      * or could not be cancelled for some other reason. If successful,
    556      * and this task has not started when <tt>cancel</tt> is called,
    557      * this task should never run. If the task has already started,
    558      * then the <tt>mayInterruptIfRunning</tt> parameter determines
    559      * whether the thread executing this task should be interrupted in
    560      * an attempt to stop the task.</p>
    561      *
    562      * <p>Calling this method will result in {@link #onCancelled(Object)} being
    563      * invoked on the UI thread after {@link #doInBackground(Object[])} returns.
    564      * Calling this method guarantees that onPostExecute(Object) is never
    565      * subsequently invoked, even if <tt>cancel</tt> returns false, but
    566      * {@link #onPostExecute} has not yet run.  To finish the
    567      * task as early as possible, check {@link #isCancelled()} periodically from
    568      * {@link #doInBackground(Object[])}.</p>
    569      *
    570      * <p>This only requests cancellation. It never waits for a running
    571      * background task to terminate, even if <tt>mayInterruptIfRunning</tt> is
    572      * true.</p>
    573      *
    574      * @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
    575      *        task should be interrupted; otherwise, in-progress tasks are allowed
    576      *        to complete.
    577      *
    578      * @return <tt>false</tt> if the task could not be cancelled,
    579      *         typically because it has already completed normally;
    580      *         <tt>true</tt> otherwise
    581      *
    582      * @see #isCancelled()
    583      * @see #onCancelled(Object)
    584      */
    585     public final boolean cancel(boolean mayInterruptIfRunning) {
    586         mCancelled.set(true);
    587         return mFuture.cancel(mayInterruptIfRunning);
    588     }
    589 
    590     /**
    591      * Waits if necessary for the computation to complete, and then
    592      * retrieves its result.
    593      *
    594      * @return The computed result.
    595      *
    596      * @throws CancellationException If the computation was cancelled.
    597      * @throws ExecutionException If the computation threw an exception.
    598      * @throws InterruptedException If the current thread was interrupted
    599      *         while waiting.
    600      */
    601     public final Result get() throws InterruptedException, ExecutionException {
    602         return mFuture.get();
    603     }
    604 
    605     /**
    606      * Waits if necessary for at most the given time for the computation
    607      * to complete, and then retrieves its result.
    608      *
    609      * @param timeout Time to wait before cancelling the operation.
    610      * @param unit The time unit for the timeout.
    611      *
    612      * @return The computed result.
    613      *
    614      * @throws CancellationException If the computation was cancelled.
    615      * @throws ExecutionException If the computation threw an exception.
    616      * @throws InterruptedException If the current thread was interrupted
    617      *         while waiting.
    618      * @throws TimeoutException If the wait timed out.
    619      */
    620     public final Result get(long timeout, TimeUnit unit) throws InterruptedException,
    621             ExecutionException, TimeoutException {
    622         return mFuture.get(timeout, unit);
    623     }
    624 
    625     /**
    626      * Executes the task with the specified parameters. The task returns
    627      * itself (this) so that the caller can keep a reference to it.
    628      *
    629      * <p>Note: this function schedules the task on a queue for a single background
    630      * thread or pool of threads depending on the platform version.  When first
    631      * introduced, AsyncTasks were executed serially on a single background thread.
    632      * Starting with {@link android.os.Build.VERSION_CODES#DONUT}, this was changed
    633      * to a pool of threads allowing multiple tasks to operate in parallel. Starting
    634      * {@link android.os.Build.VERSION_CODES#HONEYCOMB}, tasks are back to being
    635      * executed on a single thread to avoid common application errors caused
    636      * by parallel execution.  If you truly want parallel execution, you can use
    637      * the {@link #executeOnExecutor} version of this method
    638      * with {@link #THREAD_POOL_EXECUTOR}; however, see commentary there for warnings
    639      * on its use.
    640      *
    641      * <p>This method must be invoked on the UI thread.
    642      *
    643      * @param params The parameters of the task.
    644      *
    645      * @return This instance of AsyncTask.
    646      *
    647      * @throws IllegalStateException If {@link #getStatus()} returns either
    648      *         {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
    649      *
    650      * @see #executeOnExecutor(java.util.concurrent.Executor, Object[])
    651      * @see #execute(Runnable)
    652      */
    653     @MainThread
    654     public final AsyncTask<Params, Progress, Result> execute(Params... params) {
    655         return executeOnExecutor(sDefaultExecutor, params);
    656     }
    657 
    658     /**
    659      * Executes the task with the specified parameters. The task returns
    660      * itself (this) so that the caller can keep a reference to it.
    661      *
    662      * <p>This method is typically used with {@link #THREAD_POOL_EXECUTOR} to
    663      * allow multiple tasks to run in parallel on a pool of threads managed by
    664      * AsyncTask, however you can also use your own {@link Executor} for custom
    665      * behavior.
    666      *
    667      * <p><em>Warning:</em> Allowing multiple tasks to run in parallel from
    668      * a thread pool is generally <em>not</em> what one wants, because the order
    669      * of their operation is not defined.  For example, if these tasks are used
    670      * to modify any state in common (such as writing a file due to a button click),
    671      * there are no guarantees on the order of the modifications.
    672      * Without careful work it is possible in rare cases for the newer version
    673      * of the data to be over-written by an older one, leading to obscure data
    674      * loss and stability issues.  Such changes are best
    675      * executed in serial; to guarantee such work is serialized regardless of
    676      * platform version you can use this function with {@link #SERIAL_EXECUTOR}.
    677      *
    678      * <p>This method must be invoked on the UI thread.
    679      *
    680      * @param exec The executor to use.  {@link #THREAD_POOL_EXECUTOR} is available as a
    681      *              convenient process-wide thread pool for tasks that are loosely coupled.
    682      * @param params The parameters of the task.
    683      *
    684      * @return This instance of AsyncTask.
    685      *
    686      * @throws IllegalStateException If {@link #getStatus()} returns either
    687      *         {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
    688      *
    689      * @see #execute(Object[])
    690      */
    691     @MainThread
    692     public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
    693             Params... params) {
    694         if (mStatus != Status.PENDING) {
    695             switch (mStatus) {
    696                 case RUNNING:
    697                     throw new IllegalStateException("Cannot execute task:"
    698                             + " the task is already running.");
    699                 case FINISHED:
    700                     throw new IllegalStateException("Cannot execute task:"
    701                             + " the task has already been executed "
    702                             + "(a task can be executed only once)");
    703             }
    704         }
    705 
    706         mStatus = Status.RUNNING;
    707 
    708         onPreExecute();
    709 
    710         mWorker.mParams = params;
    711         exec.execute(mFuture);
    712 
    713         return this;
    714     }
    715 
    716     /**
    717      * Convenience version of {@link #execute(Object...)} for use with
    718      * a simple Runnable object. See {@link #execute(Object[])} for more
    719      * information on the order of execution.
    720      *
    721      * @see #execute(Object[])
    722      * @see #executeOnExecutor(java.util.concurrent.Executor, Object[])
    723      */
    724     @MainThread
    725     public static void execute(Runnable runnable) {
    726         sDefaultExecutor.execute(runnable);
    727     }
    728 
    729     /**
    730      * This method can be invoked from {@link #doInBackground} to
    731      * publish updates on the UI thread while the background computation is
    732      * still running. Each call to this method will trigger the execution of
    733      * {@link #onProgressUpdate} on the UI thread.
    734      *
    735      * {@link #onProgressUpdate} will not be called if the task has been
    736      * canceled.
    737      *
    738      * @param values The progress values to update the UI with.
    739      *
    740      * @see #onProgressUpdate
    741      * @see #doInBackground
    742      */
    743     @WorkerThread
    744     protected final void publishProgress(Progress... values) {
    745         if (!isCancelled()) {
    746             getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
    747                     new AsyncTaskResult<Progress>(this, values)).sendToTarget();
    748         }
    749     }
    750 
    751     private void finish(Result result) {
    752         if (isCancelled()) {
    753             onCancelled(result);
    754         } else {
    755             onPostExecute(result);
    756         }
    757         mStatus = Status.FINISHED;
    758     }
    759 
    760     private static class InternalHandler extends Handler {
    761         public InternalHandler(Looper looper) {
    762             super(looper);
    763         }
    764 
    765         @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
    766         @Override
    767         public void handleMessage(Message msg) {
    768             AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
    769             switch (msg.what) {
    770                 case MESSAGE_POST_RESULT:
    771                     // There is only one result
    772                     result.mTask.finish(result.mData[0]);
    773                     break;
    774                 case MESSAGE_POST_PROGRESS:
    775                     result.mTask.onProgressUpdate(result.mData);
    776                     break;
    777             }
    778         }
    779     }
    780 
    781     private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
    782         Params[] mParams;
    783     }
    784 
    785     @SuppressWarnings({"RawUseOfParameterizedType"})
    786     private static class AsyncTaskResult<Data> {
    787         final AsyncTask mTask;
    788         final Data[] mData;
    789 
    790         AsyncTaskResult(AsyncTask task, Data... data) {
    791             mTask = task;
    792             mData = data;
    793         }
    794     }
    795 }
    796