[关闭]
@yudesong 2018-02-12T03:11:24.000000Z 字数 4707 阅读 596

AsyncTask源码分析

AsyncTask


AsyncTask是一个抽象类,接受三个范型参数:
- Params
在执行AsyncTask时需要传入的参数,可用于在后台任务中使用。
- Progress
后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。
- Result
当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。

继承AsyncTask类需要实现如下几个方法:
- onPreExecute()
这个方法会在后台任务开始执行之间调用,用于进行一些界面上的初始化操作,比如显示一个进度条对话框等。
- doInBackground(Params...)
这个方法中的所有代码都会在子线程中运行,我们应该在这里去处理所有的耗时任务。任务一旦完成就可以通过return语句来将任务的执行结果进行返回,如果AsyncTask的第三个泛型参数指定的是Void,就可以不返回任务执行结果。注意,在这个方法中是不可以进行UI操作的,如果需要更新UI元素,比如说反馈当前任务的执行进度,可以调用publishProgress(Progress...)方法来完成。
- onProgressUpdate(Progress...)
当在后台任务中调用了publishProgress(Progress...)方法后,这个方法就很快会被调用,方法中携带的参数就是在后台任务中传递过来的。在这个方法中可以对UI进行操作,利用参数中的数值就可以对界面元素进行相应的更新。
- onPostExecute(Result)
当后台任务执行完毕并通过return语句进行返回时,这个方法就很快会被调用。返回的数据会作为参数传递到此方法中,可以利用返回的数据来进行一些UI操作,比如说提醒任务执行的结果,以及关闭掉进度条对话框等。

实例

  1. class DownloadTask extends AsyncTask<Void, Integer, Boolean> {
  2. @Override
  3. protected void onPreExecute() {
  4. progressDialog.show();
  5. }
  6. @Override
  7. protected Boolean doInBackground(Void... params) {
  8. try {
  9. while (true) {
  10. int downloadPercent = doDownload();
  11. publishProgress(downloadPercent);
  12. if (downloadPercent >= 100) {
  13. break;
  14. }
  15. }
  16. } catch (Exception e) {
  17. return false;
  18. }
  19. return true;
  20. }
  21. @Override
  22. protected void onProgressUpdate(Integer... values) {
  23. progressDialog.setMessage("当前下载进度:" + values[0] + "%");
  24. }
  25. @Override
  26. protected void onPostExecute(Boolean result) {
  27. progressDialog.dismiss();
  28. if (result) {
  29. Toast.makeText(context, "下载成功", Toast.LENGTH_SHORT).show();
  30. } else {
  31. Toast.makeText(context, "下载失败", Toast.LENGTH_SHORT).show();
  32. }
  33. }
  34. }
  35. // 启动DownloadTask
  36. new DownloadTask().execute();

接下来分析AsyncTask的源码:

  1. public AsyncTask() {
  2. mWorker = new WorkerRunnable<Params, Result>() {
  3. public Result call() throws Exception {
  4. mTaskInvoked.set(true);
  5. Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
  6. return postResult(doInBackground(mParams));
  7. }
  8. };
  9. mFuture = new FutureTask<Result>(mWorker) {
  10. @Override
  11. protected void done() {
  12. try {
  13. final Result result = get();
  14. postResultIfNotInvoked(result);
  15. } catch (InterruptedException e) {
  16. android.util.Log.w(LOG_TAG, e);
  17. } catch (ExecutionException e) {
  18. throw new RuntimeException("An error occured while
  19. executing doInBackground()",
  20. e.getCause());
  21. } catch (CancellationException e) {
  22. postResultIfNotInvoked(null);
  23. } catch (Throwable t) {
  24. throw new RuntimeException("An error occured while executing "
  25. + "doInBackground()", t);
  26. }
  27. }
  28. };
  29. }

初始化变量mWorker、mFuture,并且将mWorker作为参数传递给mFuture
接下来分析execute()方法

  1. public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
  2. private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
  3. public final AsyncTask<Params, Progress, Result> execute(Params... params) {
  4. return executeOnExecutor(sDefaultExecutor, params);
  5. }
  6. public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
  7. Params... params) {
  8. if (mStatus != Status.PENDING) {
  9. switch (mStatus) {
  10. case RUNNING:
  11. throw new IllegalStateException("Cannot execute task:"
  12. + " the task is already running.");
  13. case FINISHED:
  14. throw new IllegalStateException("Cannot execute task:"
  15. + " the task has already been executed "
  16. + "(a task can be executed only once)");
  17. }
  18. }
  19. mStatus = Status.RUNNING;
  20. //首次调用的方法
  21. onPreExecute();
  22. mWorker.mParams = params;
  23. exec.execute(mFuture);
  24. return this;
  25. }
  26. private static class SerialExecutor implements Executor {
  27. final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
  28. Runnable mActive;
  29. public synchronized void execute(final Runnable r) {
  30. mTasks.offer(new Runnable() {
  31. public void run() {
  32. try {
  33. r.run();
  34. } finally {
  35. scheduleNext();
  36. }
  37. }
  38. });
  39. if (mActive == null) {
  40. scheduleNext();
  41. }
  42. }
  43. protected synchronized void scheduleNext() {
  44. if ((mActive = mTasks.poll()) != null) {
  45. THREAD_POOL_EXECUTOR.execute(mActive);
  46. }
  47. }
  48. }
  49. void innerRun() {
  50. if (!compareAndSetState(READY, RUNNING))
  51. return;
  52. runner = Thread.currentThread();
  53. if (getState() == RUNNING) { // recheck after setting thread
  54. V result;
  55. try {
  56. result = callable.call();
  57. } catch (Throwable ex) {
  58. setException(ex);
  59. return;
  60. }
  61. set(result);
  62. } else {
  63. releaseShared(0); // cancel
  64. }
  65. }
  66. public Result call() throws Exception {
  67. mTaskInvoked.set(true);
  68. Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
  69. return postResult(doInBackground(mParams));
  70. }
  71. private Result postResult(Result result) {
  72. Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
  73. new AsyncTaskResult<Result>(this, result));
  74. message.sendToTarget();
  75. return result;
  76. }
  77. private static class InternalHandler extends Handler {
  78. @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
  79. @Override
  80. public void handleMessage(Message msg) {
  81. AsyncTaskResult result = (AsyncTaskResult) msg.obj;
  82. switch (msg.what) {
  83. case MESSAGE_POST_RESULT:
  84. // There is only one result
  85. result.mTask.finish(result.mData[0]);
  86. break;
  87. case MESSAGE_POST_PROGRESS:
  88. result.mTask.onProgressUpdate(result.mData);
  89. break;
  90. }
  91. }
  92. }
  93. private void finish(Result result) {
  94. if (isCancelled()) {
  95. onCancelled(result);
  96. } else {
  97. onPostExecute(result);
  98. }
  99. mStatus = Status.FINISHED;
  100. }
  101. protected final void publishProgress(Progress... values) {
  102. if (!isCancelled()) {
  103. sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
  104. new AsyncTaskResult<Progress>(this, values)).sendToTarget();
  105. }
  106. }

参考文献
1.Android AsyncTask完全解析,带你从源码的角度彻底理解
2.Java多线程编程:Callable、Future和FutureTask浅析(多线程编程之四)

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注