文章目录
-
-
- 介绍
- AsyncTask 结构
- 并行执行任务
-
基于Android 9.0
介绍
AsyncTask 封装了线程池和 Handler,以用来在完成耗时操作后方便的更新 UI;
AsyncTask 是一个抽象的泛型类,它有三个泛型参数 Params, Progress, Result:
- Params:参数类型
- Progress:后台任务的执行进度类型
- Result:后台任务的返回结果类型
这三个类型对应了 AsyncTask 的4个重要方法:
- onPreExecute():在主线程执行,用来在任务执行前一些初始化工作。
- doInBackground(Params… params):在线程池中执行,用来执行任务。
- publishProgress(Progress… values):在主线程执行,被doInBackground调用来更新任务进度。
- onPostExecute(Result result):在主线程执行,接收doInBackground执行完成后的结果。
AsyncTask 结构
以下是 AsyncTask 的时序图。
时序图中的角色分别是:
- SERIAL_EXECUTOR:待执行任务的缓存队列。
- THREAD_POOL_EXECUTOR:执行任务的线程池。
- FutureTask:执行任务的封装类。
- WorkerRunnable:具体执行任务的场景类。
从时序图可以看出,WorkerRunnable 是在线程池 THREAD_POOL_EXECUTOR 的线程执行的,因此doInBackground是在子线程中执行的,而其他几个方法都是在主线程中执行的。
而调用线程池执行所有任务的地方是在 SERIAL_EXECUTOR 中,即 SerialExecutor#execute 方法中:
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();Runnable mActive;public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();} finally {
scheduleNext();}}});if (mActive == null) {
scheduleNext();}}protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);}}
}
并行执行任务
可以看出 SerialExecutor 的执行逻辑是通过scheduleNext
将 mTasks,即 AsyncTask 中的所有执行任务串行执行。而我们都知道,线程池是可以并行执行的,如果我们想使 AsyncTask 并行执行任务,只需要将任务直接放入 THREAD_POOL_EXECUTOR 中,就可以达到并行的目的(实际上 AsyncTask 的早期实现就是这样的)。具体做法我们可以通过反射调用 AsyncTask的setDefaultExecutor 方法(该方法被隐藏)将 AsyncTask.THREAD_POOL_EXECUTOR 作为参数传进去,以取代SERIAL_EXECUTOR:
ReflectUtils.reflect(AsyncTask.class).method("setDefaultExecutor", AsyncTask.THREAD_POOL_EXECUTOR);