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 需要在主线程中创建.


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


2.  executeOnExecutor 中的实现 是

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


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



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 任务.



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


 


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

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

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


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


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


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


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

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


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


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


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


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


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


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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容