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<URL, Integer, Long> { 73 * protected Long doInBackground(URL... urls) { 74 * int count = urls.length; 75 * long totalSize = 0; 76 * for (int i = 0; i < 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<Void, Void, Void> { ... } 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 execute(final Runnable r)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 scheduleNext()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 getMainHandler()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 getHandler()335 private Handler getHandler() { 336 return mHandler; 337 } 338 339 /** @hide */ 340 @UnsupportedAppUsage setDefaultExecutor(Executor exec)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 */ AsyncTask()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 */ AsyncTask(@ullable Handler handler)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 */ AsyncTask(@ullable Looper callbackLooper)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 postResultIfNotInvoked(Result result)407 private void postResultIfNotInvoked(Result result) { 408 final boolean wasTaskInvoked = mTaskInvoked.get(); 409 if (!wasTaskInvoked) { 410 postResult(result); 411 } 412 } 413 postResult(Result result)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 */ getStatus()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 doInBackground(Params... params)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 onPreExecute()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 onPostExecute(Result result)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 onProgressUpdate(Progress... values)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 onCancelled(Result result)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 onCancelled()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 */ isCancelled()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 */ cancel(boolean mayInterruptIfRunning)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 */ get()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 */ get(long timeout, TimeUnit unit)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 execute(Params... params)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 executeOnExecutor(Executor exec, Params... params)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 execute(Runnable runnable)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 publishProgress(Progress... values)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 finish(Result result)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 { InternalHandler(Looper looper)761 public InternalHandler(Looper looper) { 762 super(looper); 763 } 764 765 @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"}) 766 @Override handleMessage(Message msg)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 AsyncTaskResult(AsyncTask task, Data... data)790 AsyncTaskResult(AsyncTask task, Data... data) { 791 mTask = task; 792 mData = data; 793 } 794 } 795 } 796