简单了解下AsyncTask源码,作为以后复习时用。
package: android.os;
功能:在进行异步请求时,解决子线程和主线程之间的通讯等。
此类为:抽象类,因此不能实例化,需要继承自它,再使用。
源码解析
AsyncTask 类包含:
- 3个静态内部类 [AsyncTaskResult、InternalHandler、SerialExector]
- 1个静态内部抽象类 [WorkerRunnable]
- 1个枚举类 [Status]
线程池部分:
1 | /** |
其中参数:
1 | private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); |
1 | 阻塞队列长度为128 |
使用中重要的方法:
1 | // 任务开始前需要的操作:主线程 |
execute执行方法:
1 | 第一种:需要传入调度器和参数 |
默认调度器:sDefaultExecutor
1 | private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; |
SerialExecutor 介绍
- SerialExecutor是通过ArrayDeque这个队列管理Runnable的,当我们启动了很多个任务,首先在第一次运行execute()方法的时候,会调用ArrayDeque的offer()方法将传入的Runnable对象添加到队列的尾部,然后判断mActive对象是不是等于null, 第一次运行肯定是null了,于是调用scheduleNext()方法。这个队列会从头部取值,并赋值给mActive对象,然后调用THREAD_POOL_EXECUTOR.execute(mActive)方法,去执行取出的Runnable对象。
- execute 和 scheduleNext 都被synchronized修饰,因此这两个方法拥有同一把对象锁,不可以同时运行,在execute方法中,r.run()方法为子线程中的耗时任务,当执行完成后,最终会进入到finally中调用scheduleNext去取下一个top任务。
- mTasks.offer是每次来了task都放到ArrayDeque的尾部,保证先来的先被执行。
executeOnExecutor()方法:
1 | public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, |
executeOnExecutor方法中执行了onPreExecute(),然后执行了exec.execute(mFuture);
其中Future为:
1 | mFuture = new FutureTask<Result>(mWorker) { |
从executeOnExecutor方法执行中可以看出,AsyncTask内,在主线程中先执行了onPreExecute()方法,然后在线程中调用了doInBackground()方法,任务执行完成后,通过postResult 或者 postResultIfNotInvoked 方法发送消息到主线程
postResult方法
1 | private void postResultIfNotInvoked(Result result) { |
postResult方法的作用即为任务结束后,发送message给主线程,反馈Result结果。
1 | private static class InternalHandler extends Handler { |
接收结果的为InternalHandler类,接收到结果并调用mTask的finish方法并把结果返回过去。
finish方法
1 | private void finish(Result result) { |
当Task结束后,会调用finish方法,如AsyncTask已经被取消,则会返回onCancelled回调,当未被取消则会调用onPostExecute回调。因此,onPostExecute回调也是主线程。
总结:
过去一直在用AsyncTask,也知道怎样调用,但并不知道它的工作原理,经过我们分析源码可以看到,AsyncTask为我们做了很好的线程管理(在应用中滥用线程,会造成线程过多引起很严重的问题),提供了执行前,执行中进度条更新,执行后等回调操作,便利了我们使用。