飞道的博客

Android进阶-2-源码实现-AsyncTask

375人阅读  评论(0)

目录

1、背景

2、简介

2.1、详解

2.2、使用

3、源码详解

3.1、new AsyncTask()

3.2、execute()

4、手写代码


1、背景

在Android中,除了Thread扮演线程角色以外,还有AsyncTask、HandlerThread、IntentService同样可以担当起异步线程的任务,它们各自有自己的适用场景。

AsyncTask:封装了Handler和线程池,它主要是为了方便开发者在子线程中更新UI;

HandlerThread:简化了我们创建子线程Handler的过程,简化我们线程间消息传递的过程;

IntentService:内部使用了HandlerThread,它相当于一个后台线程,单相对于Thread来说,它继承了四大组件Service,所以它的优先级会高点,不容易被系统杀死。很适合后台下载类似的任务。

2、简介

AsyncTask是一个轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行任务的进度和结果传递给主线程,并在主线程中进行更新UI的操作。

AsyncTask内部实现:使用线程池来执行异步任务,然后通过Handler来将异步任务的结果,推送到我们的UI线程。

注意:AysncTask并不适合执行一些特别耗时的操作,对于特别耗时的任务,建议使用线程池。

2.1、详解

AsyncTask是一个抽象的范型类。

Params:表示参数的类型;

Progres:表示后台任务的执行进度的类型;

Result:表示后台任务返回的结果。

Async提供了四个主要的方法。除了doInBackground()方法在异步线程外,其他的三个方法都在主线程中。

2.2、使用

这里我们继承实现了AsyncTask,然后传入1、2、3三个int值,然后在异步线程池中进行相加,并且每次睡眠3秒,最后将和传到我们的UI线程,看最后的输出结果,我们也能看到只有doInBackground()在异步的线程池中执行。其余的方法都在UI线程中。


  
  1. public class Test_My_AsyncTask extends AsyncTask<Integer, Integer, String> {
  2. @Override
  3. protected void onPreExecute() {
  4. super.onPreExecute();
  5. log( "onPreExecute.准备");
  6. }
  7. @Override
  8. protected String doInBackground(Integer... integers) {
  9. int add = 0;
  10. for (Integer i : integers) {
  11. publishProgress(i);
  12. try {
  13. Thread.sleep( 3000);
  14. } catch (InterruptedException e) {
  15. e.printStackTrace();
  16. }
  17. add = add + i;
  18. log( "doInBackground.add=" + add);
  19. }
  20. String result = "参数之和=" + add;
  21. return result;
  22. }
  23. @Override
  24. protected void onProgressUpdate(Integer... values) {
  25. super.onProgressUpdate(values);
  26. for (Integer i : values) {
  27. log( "onProgressUpdate.进度:" + i);
  28. }
  29. }
  30. @Override
  31. protected void onPostExecute(String s) {
  32. super.onPostExecute(s);
  33. log( "onPostExecute.结果:" + s);
  34. }
  35. private void log(String msg) {
  36. Log.e( "Test_AsyncTask",String.format( "%tr", new Date()) + ": "
  37. + Thread.currentThread().getName() + ": " + msg);
  38. }
  39. }
  40. ----------------------调用---------------------------------
  41. Test_AsyncTask test = new Test_AsyncTask()
  42. test.execute( 1, 2, 3)
  43. -----------------------结果---------------------------------

3、源码详解

从上面的使用来看,我们运行Test_My_AsyncTask的时候,只需要new出来Test_My_AsyncTask对象,然后执行它的execute()方法。

那么我们首先看一下AsyncTask的构造函数都做了什么操作?

3.1、new AsyncTask()

看下图:

当我们new 一个AsyncTask对象的时候:

1、我们会创建一个主线程的Handler

2、我们的doInBackground()函数会被放在一个类似线程的执行对象Runnable中;

3、然后我们的doInBackground()函数返回的结果会通过Handler发送到主线程中,并且调用onPostExecute()函数。

4、当然到现在,onPostExecute()还没有被执行,因为我们还没有diao

注意:如果你想要了解Callback 和FutureTask,可以进入这个连接了解一下,如果不想了解,可以把它们当成Runnable也行。

3.2、execute()

execute()的执行:

1、会先调用onPreExecute();

2、sDefaultExecutor线程池会执行我们前面类似Runnable的FutureTask对象,这样就会执行doInBackground()方法。

3、而且在sDefaultExecutor线程池中,我们的doInBackground()并没有执行,只是被添加到一个ArrayDeque中,真正执行该任务的是THREAD_POOL_EXECUTOR线程池。

4、这样我们整个流程就算完成了。

注意:从ArrayDeque来看,默认情况,我们的AsyncTask是串行执行的。

4、手写代码

Async类


  
  1. package com.yobo.yo_android.test_AsyncTask;
  2. import android.os.Handler;
  3. import android.os.Looper;
  4. import android.os.Message;
  5. import java.util.ArrayDeque;
  6. import java.util.concurrent.BlockingQueue;
  7. import java.util.concurrent.Callable;
  8. import java.util.concurrent.ExecutionException;
  9. import java.util.concurrent.Executor;
  10. import java.util.concurrent.FutureTask;
  11. import java.util.concurrent.LinkedBlockingQueue;
  12. import java.util.concurrent.ThreadFactory;
  13. import java.util.concurrent.ThreadPoolExecutor;
  14. import java.util.concurrent.TimeUnit;
  15. import java.util.concurrent.atomic.AtomicBoolean;
  16. import java.util.concurrent.atomic.AtomicInteger;
  17. public abstract class AsyncTask<Params, Progress, Result> {
  18. private static final int MESSAGE_POST_RESULT = 0x1;
  19. private static final int MESSAGE_POST_PROGRESS = 0x2;
  20. private final WorkerRunnable<Params, Result> mWorker;
  21. private final FutureTask<Result> mFuture;
  22. private final Handler mHandler;
  23. private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
  24. public AsyncTask() {
  25. mHandler = new InternalHandler(Looper.getMainLooper());
  26. mWorker = new WorkerRunnable<Params, Result>() {
  27. @Override
  28. public Result call() {
  29. mTaskInvoked.set( true);
  30. Result result = doInBackground(mParams);
  31. postResult(result);
  32. return result;
  33. }
  34. };
  35. mFuture = new FutureTask<Result>(mWorker) {
  36. @Override
  37. protected void done() {
  38. super.done();
  39. try {
  40. postResultIfNotInvoked(get());
  41. } catch (ExecutionException | InterruptedException e) {
  42. e.printStackTrace();
  43. }
  44. }
  45. };
  46. }
  47. private void postResultIfNotInvoked(Result result) {
  48. boolean wasTaskInvoked = mTaskInvoked.get();
  49. if (!wasTaskInvoked) {
  50. postResult(result);
  51. }
  52. }
  53. private void postResult(Result result) {
  54. Message message = mHandler.obtainMessage(MESSAGE_POST_RESULT,
  55. new AsyncTaskResult<>( this, result));
  56. message.sendToTarget();
  57. }
  58. @SafeVarargs
  59. public final AsyncTask<Params, Progress, Result> execute(Params... params) {
  60. return executeOnExecutor(sDefaultExecutor, params);
  61. }
  62. @SafeVarargs
  63. private final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
  64. Params... params) {
  65. onPreExecute();
  66. mWorker.mParams = params;
  67. exec.execute(mFuture);
  68. return this;
  69. }
  70. private static class InternalHandler extends Handler {
  71. InternalHandler(Looper looper) {
  72. super(looper);
  73. }
  74. @SuppressWarnings({ "unchecked", "RawUseOfParameterizedType" })
  75. @Override
  76. public void handleMessage(Message msg) {
  77. AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
  78. switch (msg.what) {
  79. case MESSAGE_POST_RESULT:
  80. // There is only one result
  81. result.mTask.finish(result.mData[ 0]);
  82. break;
  83. case MESSAGE_POST_PROGRESS:
  84. result.mTask.onProgressUpdate(result.mData);
  85. break;
  86. }
  87. }
  88. }
  89. private abstract static class WorkerRunnable<Params, Result> implements Callable<Result> {
  90. Params[] mParams;
  91. }
  92. private static class AsyncTaskResult<Data> {
  93. final AsyncTask mTask;
  94. final Data[] mData;
  95. @SafeVarargs
  96. AsyncTaskResult(AsyncTask task, Data... data) {
  97. mTask = task;
  98. mData = data;
  99. }
  100. }
  101. private void finish(Result result) {
  102. onPostExecute(result);
  103. }
  104. final void publishProgress(Progress... values) {
  105. mHandler.obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<>( this, values))
  106. .sendToTarget();
  107. }
  108. /**
  109. * 运行在主线程中,doInBackground()之前就会被调用,可以做一些准备操作
  110. */
  111. protected void onPreExecute() {
  112. }
  113. /**
  114. * 运行在线程池中,执行异步任务的地方
  115. */
  116. protected abstract Result doInBackground(Params... params);
  117. /**
  118. * 运行在主线程之中,可以在doInBackground()中调用publishProgress()函数来触发该方法
  119. */
  120. protected void onProgressUpdate(Progress... values) {
  121. }
  122. /**
  123. * 运行在主线程之中,doInBackground()返回的Result结果会被推送这里
  124. */
  125. protected void onPostExecute(Result result) {
  126. }
  127. /**
  128. * -------------------------线程池的创建------------------------------------------
  129. */
  130. private static final Executor sDefaultExecutor = new SerialExecutor();
  131. private static final Executor THREAD_POOL_EXECUTOR;
  132. private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<>( 128);
  133. private static final ThreadFactory sThreadFactory = new ThreadFactory() {
  134. private final AtomicInteger mCount = new AtomicInteger( 1);
  135. public Thread newThread(Runnable r) {
  136. return new Thread(r, "线程-Yobo-" + mCount.getAndIncrement());
  137. }
  138. };
  139. /**
  140. * CPU核心数量
  141. */
  142. private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
  143. static {
  144. ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(CPU_COUNT - 1,
  145. CPU_COUNT * 2 + 1, 30, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
  146. threadPoolExecutor.allowCoreThreadTimeOut( true);
  147. THREAD_POOL_EXECUTOR = threadPoolExecutor;
  148. }
  149. private static class SerialExecutor implements Executor {
  150. final ArrayDeque<Runnable> mTasks = new ArrayDeque<>();
  151. Runnable mActive;
  152. public synchronized void execute(final Runnable r) {
  153. mTasks.offer( new Runnable() {
  154. public void run() {
  155. try {
  156. r.run();
  157. } finally {
  158. scheduleNext();
  159. }
  160. }
  161. });
  162. if (mActive == null) {
  163. scheduleNext();
  164. }
  165. }
  166. synchronized void scheduleNext() {
  167. if ((mActive = mTasks.poll()) != null) {
  168. THREAD_POOL_EXECUTOR.execute(mActive);
  169. }
  170. }
  171. }
  172. }

Test_My_AsyncTask


  
  1. package com.yobo.yo_android.test_AsyncTask;
  2. import java.util.Date;
  3. import android.util.Log;
  4. public class Test_My_AsyncTask extends AsyncTask<Integer, Integer, String> {
  5. @Override
  6. protected void onPreExecute() {
  7. super.onPreExecute();
  8. log( "onPreExecute.准备");
  9. }
  10. @Override
  11. protected String doInBackground(Integer... integers) {
  12. int add = 0;
  13. for (Integer i : integers) {
  14. publishProgress(i);
  15. try {
  16. Thread.sleep( 3000);
  17. } catch (InterruptedException e) {
  18. e.printStackTrace();
  19. }
  20. add = add + i;
  21. log( "doInBackground.add=" + add);
  22. }
  23. String result = "参数之和=" + add;
  24. return result;
  25. }
  26. @Override
  27. protected void onProgressUpdate(Integer... values) {
  28. super.onProgressUpdate(values);
  29. for (Integer i : values) {
  30. log( "onProgressUpdate.进度:" + i);
  31. }
  32. }
  33. @Override
  34. protected void onPostExecute(String s) {
  35. super.onPostExecute(s);
  36. log( "onPostExecute.结果:" + s);
  37. }
  38. private void log(String msg) {
  39. Log.e( "Test_AsyncTask",String.format( "%tr", new Date()) + ": "
  40. + Thread.currentThread().getName() + ": " + msg);
  41. }
  42. }

 


转载:https://blog.csdn.net/qq_34589749/article/details/105663943
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场