AsyncTask简单来说就是Android自身提供的一个简化后台读取数据,主线程更新UI的帮助类,避免了开发者自身去实现Thread和Handler的逻辑。
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
AsyncTask的基本使用就是4个回调方法
onPreExecute()
doInBackground(Params... params)
onProgressUpdate(Progress… value)
onPostExecute(Result result)
AsyncTask内部使用了一个SerialExecutor的执行器来执行任务,从名字就可以看出该执行器是串行执行任的,如果是通过以下代码来开启多个AsyncTask的执行,那么Tasks之间并不是并行的关系,而是一个完成之后再继续下一个的串行关系。
asyncTask.execute(params);
SerialExecutor的实现
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每次的execute是先将需要执行任务封装进一个添加了任务调度逻辑的任务中,并将该任务添加至队列中,最后再根据当前有无正在执行的任务决定是否开启新一轮的串行任务执行。
如果我们想要多个AsyncTask并行执行应该怎么办呢?
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params)
这是AsyncTask提供的另一个开启任务的方法,该方法是可以指定Executor的,AsyncTask除了SerialExecutor还提供了另一个执行器THREAD_POOL_EXECUTOR,一个 支持最多128个待唤醒任务的并行Executor。
使用一下代码就可以让多个任务并行执行
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,params);
当然如果AsyncTask提供的执行器不能满足需求,开发者还可以定义自己的Executor。
另外AsyncTask有一个被隐藏的设置执行器的方法,作为内部方法使用
/** @hide */
public static void setDefaultExecutor(Executor exec) {
sDefaultExecutor = exec;
}
毕竟如果在多个AsyncTask执行期间调用该方法来切换默认执行器的话容易造成Task的调用混乱。
之前说到AsyncTask的的基本使用就是4个步骤,并且4步是执行在不同的线程的,那这是如何实现的呢?
简单描述下就是AsyncTask是通过WorkRunnable, FutureTask, Handler走完自己的基本生命周期的。在execute(params..)或者executeOnExecutor(executor, params...)之后onPreExecute()就会被调用,紧接着params会传递到一个WorkRunnable实例中,该实例和FutureTask的实例一样都是在AsyncTask的构造函数中实例化和初始化的,然后是将包含了该WorkRunnable实例的FutureTask实例加入执行器中等待执行,当该任务被执行到时,WorkRunnable会负责执行doInBackground(params)然后将返回的结果通过postResult(result)发送,其实现就是通过Handler发送一条状态为执行完成的消息,Handler处理消息则会根据当前AsyncTask是否已经被取消调用onCancelled(result)或者onPostExecute(result),这样一个任务就执行完成了。至于onProgressUpdate(progress)则是在调用publishProgress(progress)后通过Handler发送状态为更新的消息。
最后关于AsyncTask的使用有一点需要注意的是它的生命周期比较难确定,即使是调用了cancel(interrupt = true)方法也不能保证AsyncTask会直接挂掉,所以如果是在Activity等上下文中使用AsyncTask的话就需要注意内存泄漏问题,尤其是由于屏幕旋转造成的Activity生命周期变化问题,最好不要使用匿名内部类这样的实例化方式。
以上基于SDK-24源码,如有问题请指正。