AsyncTask原理详解!

本文详细介绍AsyncTask的工作原理,包括核心函数如onPreExecute、doInBackground等的作用及交互方式,揭示了AsyncTask如何实现子线程与UI线程的通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在项目中子线程和UI线程交互过程中,经常会用到AsyncTask,AsyncTask使用场景有网络访问、上传文件等。

AsyncTask的核心原理有以下几条,请配合后面详解来理解。
1、 AsyncTask主要使用的4个函数,onPreExecute、doInBackground、 onProgressUpdate、onPostExecute。
2、onPreExecute是在AsyncTask,execute()中最先执行!
3、doInBackground 和 onProgressUpdate的交互。doInBackground 中执行 publishProgress,publishProgress将doInBackground 传过来的值通过UI线程的Handler发送 给UI线程,UI线程收到通过onProgressUpdate进行处理。
4、doInBackground 和 onPostExecute的交互。doInBackground 中执行完毕会通过UI线程 的handler把结果传递给UI线程,UI线程会根据本消息类型交给onPostExecute处理!
5、doInBackground 的执行是在 AsyncTask中实现的一个Callable的call中执行的,这就是为 什么doInBackground 是在子线程中执行!
6、AsyncTask的所有运行是在线程池中处理的。 AsyncTask中会有一个继承于Executor的 类SerialExecutor。SerialExecutor中会有一个数组队列存储每一次Task并且每次会从本数组队列的头部取出一个放在线程池中执行!


本文不再详细讨论AsyncTask的具体使用,而是通过图解形式来对AsyncTask的实现原理进行详细讲解,如果查看的图片不清晰,请放大浏览器。

1、参见以下截图,展现了AsyncTask的使用及其说明!
这里写图片描述


2、通过上面的AsyncTask实现可以发现,其主要有4个方法,现在来研究下AsyncTask的构造函数,见下图!
mWorker继承于Callable,mFuture继承于FutureTask,doInBackground是运行在mWorker中,因此这里证明了doInBackground在子线程中执行!Callable 和 FutureTask见博客最后会讲解。

这里写图片描述


3、见下图,mFuture中的对mWorker返回的result的处理函数postResultIfNotInvoked,从内部源代码可以发现最终是将doInBackground执行的结果通过主线程的Handler发送给了UI线程。这里就实现子线程和主线程的交互的交互!

这里写图片描述


4、使用AsyncTask的时候都非常清楚,在doInBackground中执行结果最终是会交给UI线程运行的onPostExecute处理的,居然doInBackground通过UI线程的Handler发送给UI线程,那么可以想到,UI线程的handleMessage会对其进行处理!请参见以下UI线程的Handler源码截图和说明!

这里写图片描述

看下publishProgress的实现:

这里写图片描述

主线程中的handleMessage会处理两个message,一个是MESSAGE_POST_RESULT(这个就是发送doInBackground结果的信息messageType),另外一个是MESSAGE_POST_PROGRESS( onProgressUpdate处理这个信息可知, doInBackground 中通过 publishProgress把更新值通过Handler传送到这里,交给onProgressUpdate处理,doInBackground 和 onProgressUpdate之间的交互即在此)。

看看finish是怎么实现的,见下图:

这里写图片描述


5、参见以下AsyncTask.execute源码解析。execute调用的是executeOnExecutor,图示对源码进行了详细解析。

这里写图片描述


**6、**sDefaultExecutor中execute的参数传过来的是mFuture,参见下图中sDefaultExecutor源码解析截图。

这里写图片描述

从sDefaultExecutor源码中可以发现最终每个任务会放进一个队列,每次从first取一个放在线程 池中执行!而mFuture.run() 最终是在sDefaultExecutor.execute执行的,也就是最终是在线程池中执行!。

见下图对线程池的定义:

这里写图片描述


AsyncTask缺点:

  • AsyncTask实现 和 execute的启动只能在主线程中执行。
  • AsyncTask中的 execute只能执行一次,根据AsyncTask源码分析可知,AsyncTask定义了一个变量mStatus,该变量指定了AsyncTask的状态,如果在运行则为RUNNIING,运行中再次执行execute,则抛出异常。
  • 如果AsyncTask在 Activity中定义为非静态的,则当Activity关闭GC之后 AsyncTask并不会随着Activity的生命周期的结束而结束,当 AsyncTask执行 doInBackgroud之后返回主线程,更新主线程的view的时候 则因为view 已经不存在,则会抛出异常。
  • 如果AsyncTask在 Activity中定义为静态的,因为AsyncTask持有了Activity的context,则当Activity关闭进行GC的时候, 因为AsyncTask 持有 Activity的context 则导致 Activity关闭失败,就造成了内存泄漏。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值