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