本文AsyncTask源码sdk版本为23,资料来源参考《Android开发艺术》
一、为什么使用AsyncTask
避免了每次开启一个线程thread,都需要写一个handler去通知主线程更新,就是Google帮大家封装了thread和handler。
AsyncTask并不适合进行特别耗时的后台任务,对于特别耗时的任务来说,建议使用线程池。
这是主席在开发艺术中的原话,但AsyncTask中的实现,在sdk23中是使用了线程池的,都是使用线程池,那在AsyncTask中做耗时任务,与自己单独使用线程池有什么区别,这里略有疑问。
二、内部实现
首先,这玩意是个抽象类。所以你必须写一个自己的task去继承AsyncTask,并重写几个核心方法。这点可以很好理解为,整体的内部逻辑实现好了,关键的那几个步骤,你自己去重写,你想咋干咋干。根据这个,AsyncTask使用了模板模式,具体实现方法由子类重写。
那看看AsyncTask需要重写哪几个核心方法。
protected abstract Result doInBackground(Params... params);
protected void onPreExecute() {}
protected void onPostExecute(Resultresult) {}
protected voidonProgressUpdate(Progress... values) {}
protected void onCancelled() {}
其中doInBackground方法为抽象方法是必须要重写的,这是肯定的,就指着这方法在线程中执行。其他的protected方法也是希望你去重写的,注意一点,方法体内都为空,更说明了使用了模板模式。
整体实现逻辑流程
先整体看看大致实现,全局掌控,心里有底不虚。
先要有两个概念,callable 接口和future类,这是带返回值的线程使用。毕竟AsncTask在任务执行完后要可以提供返回值。
我们在使用AsyncTask时都是自己写一个类继承它,然后实例一个对象,然后执行execute()方法。
那我们就从它的构造方法看起
public AsyncTask() {
mWorker=new WorkerRunnable() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
return postResult(result);
}
};
mFuture=new FutureTask(mWorker) {
@Override
protected voiddone() {
//.......省略代码
}
};
}
诶~! 有一个很眼熟的方法 有木有,doInBackground,看来我们自己实现的doInBackground就在这里执行了。WorkerRunnabler实现了Callable接口,所以线程执行就在这里了。那就还需要一个FutureTask了,下面mFuture就是个FutureTask,看来AsyncTask就是靠这两个API;
好接下来看execute方法。
public final AsyncTask execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
看来执行放在了executeOnExecutor(Executor exec,Params… params)中。两个参数一个是Executor,看来是会用到线程池,一个params参数
public finalAsyncTask executeOnExecutor(Executor exec,Params... params) {
//......省略
mStatus= Status.RUNNING;
onPreExecute();
mWorker.mParams= params;
exec.execute(mFuture);
return this;
}
又看到了熟悉的函数onPreExecute,在任务执行前,先执行onPreExeute方法。将参数params赋值给mWorker的mParams,也就是构造其中的doInBackground的参数就是从这里传过去的。
好了执行异步任务的逻辑就这么基本走完了。那线程结束后是如何通知主线程的呢,那就要用到handler了。
我们在回过头看看构造器中WorkRunnable的返回值是什么 返回了一个方法postResult(result)
private Result postResult(Result result) {
Message message =getHandler().obtainMessage(MESSAGE_POST_RESULT,
newAsyncTaskResult(this, result));
message.sendToTarget();
return result;
}
看来postResult中通过使用了handler发送消息给主线程,然后在通过handler的handlerMessage方法处理传递来的消息。
好了 AsyncTask的整体实现逻辑也就到此了。下一篇笔记将继续深入学习AsyncTask是如何通过handler与线程交互的AsyncTask源码学习笔记二。