AsyncTask 的源码实现(完结)

AsyncTask 的作用: 

     是 隐藏 多线程的管理 , 以简单的形式 提供 多线程支持.  在实践中 可以把一些 耗时操作 或者 网络请求 放到 AsynTask 中 去执行. 

AsyncTask 的使用:

     很 简单, 在 UI 线程中 创建 一个 AsyncTask 的对象[为啥 一定在UI 线程中呢,下面有讲解.] 并实现 doInBackground 方法, 启动 doInBackground() 方法是在 另一个线程中执行的, 当 执行完之后 onPostExecute() 会被在 UI 线程中调用执行. onProgressUpdate[在 UI 线程中被调用] 和 publishProgress() [在 doInBackground 中被调用]两个方法是用来 汇报 doInBackground() 中 任务执行的进度的.

  -----------------------------------------------------------------------------------------------------------------------------------------------------------------------      
AsyncTask 的源码 解读:

1. 为什么 一定要在 UI 线程中 创建AsyncTask 的对象呢, 因为: 第一次 加载的 AsyncTask 这个类的时候 会创建 InternalHandler() 这个对象, 这个是 Handler对象的子类, 只 重写了 handleMessage() 方法, 
    当 我们使用 无参 构造函数 创建 Handler 对象的时候 取的 Looper 对象 是当前线程的, 因为 这个 InternalHandler() 对象是 AsynTask 的工作 线程 和 主线程 进行通信的 因此 AsyncTask 需要在主线程中创建.

AsyncTask 的源码实现(完结)_第1张图片


2. 因为AsyncTask 的神秘性, 我们从 使用的 角度 作为 入口点进行分析,  从 AsyncTask 的 execute 方法开始 分析,  在 execute 中 实际上 是调用 executeOnExecutor() 方法, 在 其 实现中 是 执行了 SerialExecutor 对应的 execute 方法.  sDefaultExecutor 为 SerialExecutor  的 静态全局 对象, 

AsyncTask 的源码实现(完结)_第2张图片


2.  executeOnExecutor 中的实现 是

     第一个: 先 执行 onPreExecute()  方法, 官方建议 在 onPreExecute() 中 开启 进度条, 因此 execute 也需要在 UI 线程中执行 ( 第一个 需要自定义的方法被执行了, 在UI 线程中)


     第二个: 用 sDefaultExecutor 调用 execute 方法, 并把 创建 AsyncTask 时 对应的 mFuture 对象  作为 参数传入. 注意 我们 通过 execute 传进来的参数 params 被 赋值给了 mWorker.mParams. ( 其中 mFuture 和 mWorker 会在下面 讲 AsyncTask 的构造函数的时候进行讲解).


AsyncTask 的源码实现(完结)_第3张图片


3. 其中 sDefaultExecutor的 execute方法 对应的实现为: execute 的实现 是 把要执行的 Runnable 放到 mTasks 对应的队列中((这个 Runnable 实际上是 AsyncTask 中 对应的 mFuture 对象 )) , 当mActive ==null 的时候,即还没有Task 正在执行 ,则 调用 scheduleNext() ,  而 scheduleNext() 的实现很简单:  从 mTasks(Runnable Task 的队列) 中取出 一个 Runnable 然后赋值 给 mActive, 然后丢到 线程池中开始执行.


> 在最开始的时候是 执行一个任务, 从 SerialExecutor 中的 execute 方法中  mTasks.offer () 对应的语句 可以知道, 当 只有当 execute()函数传来的 Runnable 执行完的时候才会开始执行一下 mTasks 中的 Task 任务.

AsyncTask 的源码实现(完结)_第4张图片



> 在 handleBindApplication 方法中, 判断 如果 android 系统的 api 级别 为 12( 3.1) 或者 为 12 以下, 则 设置 AsyncTask.THREAD_POOL_EXECUTOR 为 默认的 executor, 则 可以 使用 多个 线程 一起执行 AsyncTask 中的任务.


 

AsyncTask 的源码实现(完结)_第5张图片

4.     从上面 我们知道 AsyncTask 的执行 实际上 是 把 mFuture 对象丢到 线程池中, 则  AsyncTask 的 主要 逻辑( doBackGround, 和 onPostExecute(), publishProgess, onProgressExecute 等的调用) 应该都和 FutureTask 有着半毛钱的关系,在 创建 FutureTask 对象的时候 是把 mWorker (WorkerRunnable) 作为 Callable 接口的实现 传入. 在 FutureTask 的 run 方法(这个方法会被放到线程池中执行) 会 调用 Callable 接口 对应的 call() 方法, 即 下面看到的 postResult(doInBackground(mParams));  这个 语句.

回顾 : 在 execute() 方法的 中获取到的参数 会 赋值 给 mWorker 的 mParams 属性.

在 AsyncTask 的方法中, AsyncTask 的构造函数主要是 创建 mWorker 对象(WorkderRunnable) 和 mFuture 对象(FutureTask).

AsyncTask 的源码实现(完结)_第6张图片

5.   FutureTask  是 实现了 RunnableFuture 这个接口, 而 RunnableFuture 继承了 接口 Runnable 和 Future, 其中 Future 接口 如下图 其 主要作用是控制任务的执行 赋予任务可以被取消的能力 , 由于 FutureTask 是 一个 Runnable 的 实现类,因此 可以被用来 丢到 线程池中进行执行.

AsyncTask 的源码实现(完结)_第7张图片

6.  FutureTask 对 RunnableFuture 的实现为:  通过 Sync 对象 来 控制 线程同步 以及 任务执行时的 控制, 比如进行取消.

AsyncTask 的源码实现(完结)_第8张图片

7. 关于 mWorker 的实现为:  mWorker 是 WorkerRunnable 的匿名实现类,  WorkerRunnable 抽象类 实际 上只是 带 mParams 属性的 Callable 接口.

AsyncTask 的源码实现(完结)_第9张图片

8.  匿名实现类 中的 call 实现为: 

设置线程 为  后台线程, 然后 调用  doInBackground() 方法, 把返回的结果传给 postResult.

AsyncTask 的源码实现(完结)_第10张图片

9.  postResult 会向  sHandler 发送 一个 message_post_result 的 Message 消息, 其 对应的 obj 为  AsyncTaskResult(AsyncTask.this, result), 这个result 为 doInBackground 返回的 结果

AsyncTask 的源码实现(完结)_第11张图片

10. 在InternalHandler 对应的 handleMessage 中 会 调用 msg.obj.mTask.finish 方法, 把 msg.obj.mData[0]作为参数传进去.

AsyncTask 的源码实现(完结)_第12张图片
AsyncTask 的源码实现(完结)_第13张图片

11.  在 AsyncTask 的 finish 方法中 则 是 执行 onPostExecute 方法, : 如果 之前 设置了 状态为 cancel, 则 只会执行 onCancelled (Result) 方法.

AsyncTask 的源码实现(完结)_第14张图片

12.   当我们在 执行 doInBackground 的时候, 如果需要 通知 UI , 则 调用 publishProgress(Progress... values) 方法, 

AsyncTask 的源码实现(完结)_第15张图片

13.   在 message_post_progress 对应的 handleMessage 方法为:

AsyncTask 的源码实现(完结)_第16张图片

14. AsyncTask 对应的 onProgressUpdate 方法为: 这个 方法 中 是用来 更新 UI 中的 处理 进度条的.

AsyncTask 的源码实现(完结)_第17张图片

你可能感兴趣的:(AsyncTask 的源码实现(完结))