一、原理

AsyncTask 本质上是对handler和线程池对封装,在线程池中执行耗时任务,当任务完成或任务更新时,向主线程的Handler发送消息,在Handler中执行finish()onProgressUpdate()等方法。

二、并行还是串行执行

从 1.5 引入的时候的确是串行的,在 1.6-2.3.2 的时候执行顺序更改为并行了,在 3.0 之后又改回了串行。

2.1 并行执行

并行执行任务的方法:executeOnExecutor(AsyncTask.THREAD_POOL_EXRCUTOR);
或者使用自己的创建的线程池。

2.2 串行执行

通过SerialExecutor来控制,由于AsyncTask中的控制线程池sDefaultExecutor是静态的,因此一个进程内的所有AsyncTask共用一个线程池。
如何控制串行执行?
SerialExecutor中,线程是在scheduleNext()中提交给线程池执行的。
1、当SerialExecutor第一次执行线程时,mActive为空,因此会直接将线程交给线程池执行
2、当继续执行AsyncTask任务时,SerialExecutor并不会将线程提交给线程池,而是等上一个Runnable执行完成后再执行scheduleNext(),以达到串行执行的效果。

private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;

// 重写了Executor的execute方法,不直接执行线程
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);
}
}
}

三、优缺点

3.1 缺点

1、内存泄漏

如果AsyncTask被声明为Activity的非静态内部类,那么AsyncTask会保留一个对Activity的引用。如果Activity已经被销毁,AsyncTask的后台线程还在执行,它将继续在内存里保留这个引用,导致Activity无法被回收,引起内存泄漏。

2、结果丢失

屏幕旋转或Activity在后台被系统杀掉等情况会导致Activity的重新创建,之前运行的AsyncTask会持有一个之前Activity的引用,这个引用已经无效,这时调用onPostExecute()再去更新界面将不再生效。

3、生命周期

很多开发者会认为一个在Activity中创建的AsyncTask会随着Activity的销毁而销毁。然而事实并非如此。AsynTask会一直执行,直到doInBackground()方法执行完毕,然后,如果cancel(boolean)被调用,那么onCancelled(Result result)方法会被执行;否则,执行onPostExecute(Result result)方法。如果我们的Activity销毁之前,没有取消AsyncTask,这有可能让我们的应用崩溃(crash)。因为它想要处理的view已经不存在了。所以,我们是必须确保在销毁活动之前取消任务。总之,我们使用AsyncTask需要确保AsyncTask正确的取消

4、execute()只能执行一次,因为代码中判断了状态;并且只能在UI线程中调用、因为onPreExecute,在execute中被调用,而onPreExecute被限制只能在UI线程中调用

5、AsyncTask必须在主线程中创建,因为它的onPreExecute、doInBackground等方法只能在UI线程中被调用

6、api 30 (Android11)将移除该库了

image-20200727110522173

3.2 优点

可以在后台任务执行完毕时根据返回结果相应的更新 UI

参考地址

https://www.xiaoheidiannao.com/207433.html