AsyncTask原理详解!

在项目中子线程和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的使用及其说明!
AsyncTask原理详解!_第1张图片


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

AsyncTask原理详解!_第2张图片


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

AsyncTask原理详解!_第3张图片


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

AsyncTask原理详解!_第4张图片

看下publishProgress的实现:

AsyncTask原理详解!_第5张图片

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

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

AsyncTask原理详解!_第6张图片


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

AsyncTask原理详解!_第7张图片


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

AsyncTask原理详解!_第8张图片

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

见下图对线程池的定义:

AsyncTask原理详解!_第9张图片


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关闭失败,就造成了内存泄漏。

你可能感兴趣的:(ANDROID,安卓,多线程,JAVA并行计算,android核心组件,Android内核剖析,Android高级开发)