(注意:本文基于API 28的源码分析,API 29上或其他平台的源码略有不同)
前言
无参的构造方法用于创建AsyncTask对象(AsyncTask是抽象类,只能创建子类的对象),另外两个有参数的构造方法是hide修饰的,我们无法直接调用!
AsyncTask()构造方法分析
public AsyncTask() {
this((Looper) null);
}
null强制转换为Looper,然后传入只有1个参数的构造方法中。传入参数的方式,真是神奇了……
AsyncTask()构造方法分析(重载构造方法:1个参数)
public AsyncTask(@Nullable Looper callbackLooper) {
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
传入的参数为Looper对象
1、为AsyncTask对象持有的mHandler进行初始化,可能会出现的两种情况
第一:AsyncTask对象持有一个Handler对象mHandler,当传入的callbackLooper为null或者callbackLooper为主线程的Looper对象时,会调用一个getMainHandler()方法,getMainHandler()方法返回的Handler对象由mHandler负责持有,这个Handler对象是主线程的Handler对象
第二:callbackLooper即不为null、也不是主线程的Looper对象时,则会通过new一个新的Handler对象,同样由mHandler负责持有
2、为AsyncTask对象持有的mWorker进行初始化
首先创建一个WorkerRunnable对象,该对象是以匿名内部类形式创建的,在匿名内部类中重写的call()方法中做了什么呢?这个在后面后解释。WorkerRunnable类实现了Callable接口,最终这个创建的WorkerRunnable对象由AsyncTask对象持有的mWorker负责持有
3、为AsyncTask对象持有的mFuture进行初始化
先创建一个FutureTask对象,同样也是以匿名内部类形式创建的对象,然后将AsyncTask对象持有的mWorker传入到FutureTask的构造方法中,FutureTask对象负责持有一个Callable对象,在匿名内部类中重写了done()方法(本身FutureTask的done()方法的默认实现是空的,这里做了重写),最终FutureTask对象由AsyncTask对象持有的mFuture负责持有
getMainHandler()方法分析
private static Handler getMainHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler(Looper.getMainLooper());
}
return sHandler;
}
}
Looper类的静态方法getMainHandler(),用于获得主线程中的Handler对象
1、首先线程需要持有AsyncTask类的Class对象锁
2、检查AsyncTask类还有的静态变量sHandler是否已经指向一个Handler对象
当AsyncTask类持有的Handler对象没有创建时,通过new一个InternalHandler对象,该对象是主线程的Looper对象
3、向调用者返回主线程的Handler对象
最后return自定义的Handler对象sHandler
InternalHandler构造方法分析
public InternalHandler(Looper looper) {
super(looper);
}
位于AsyncTask类中,InternalHandler是一个静态内部类,它继承了Handler
call方法分析
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
WorkerRunnable中重写的call()方法
1、mTaskInvoked是AsyncTask对象持有的一个AtomicBoolean对象,AtomicBoolean对象持有的boolean值,会保证在多个线程下安全更新,单个共享变量使用原子类是非常好的,这里首先将mTaskInvoked持有的boolean值赋值为true。
2、定义了一个局部变量result,看看后面要用它做什么?
3、Process.setThreadPriority方法则会设置线程的优先级,本处传入的优先级是Process.THREAD_PRIORITY_BACKGROUND,它的优先级值是10,目的就是让执行call方法的线程优先级较低,保障UI线程的顺利执行
4、这个call方法一定在工作线程中执行,它的内部调用了doInBackground方法(见6号知识点),传入的是WorkerRunnable对象持有的Params数组类(参数类型)的一个对象mParams。这条语句说明我们每次必须重写的doInBackground方法一定是在工作线程中执行的,它的返回结果将会由局部变量result负责持有
5、Binder.flushPendingCommands(),这是一个native方法,没明白具体的作用是什么?
6、上面执行语句中,出现的任何异常对象,都会捕获到(这里捕获的是Throwable),然后调用的是mCancelled的set方法,传入的值是true,mCancelled是AsyncTask对象持有的一个AtomicBoolean对象,这里是为了线程安全的更新AtomicBoolean对象持有的boolean值
7、一定会执行的finally代码块中,则调用了一个postResult方法(见7号知识点),并将局部变量result传了进去,result变量代表的是执行结果
8、最终方法返回的是result(参数类型为Result)
done()方法分析
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
1、最先调用的是一个get方法,它是FutureTask中的一个方法
2、接着是postResultIfNotInvoked方法的调用
3、捕获InterruptedException、以及ExcutionException,分别进行处理
一个是在标准输出流中打印日志,另一个是抛出RuntimeException对
4、捕获CancllationException对象,进行处理
通过调用postResultIfNotInvoked()方法进行处理,传入的参数为null
doInBackground()方法分析
protected abstract Result doInBackground(Params... params);
在AsyncTask中定义的抽象方法,典型的模版方法模式的应用,供开发者重新用的,这个方法将在工作线程中执行
postResult()方法分析
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
1、首先通过getHandler方法(见8号知识点),获得一个Handler对象,接着调用Handler对象的obtainMessage方法,为其传入两个参数,一个是MESSAGE_POST_RESULT(常量值:0x1),另一个参数是AsyncTaskResult对象,它持有了当前的AsyncTask对象,和参数类型为Result的对象,obtainMessage方法返回的Message对象由局部变量message负责持有
2、接着为局部变量message调用一个sendToTarget方法,它会将Message对象通过Handler对象的sendMessage方法发送到MessageQueue中
3、最后返回的是Result对象
getHandler()方法分析
private Handler getHandler() {
return mHandler;
}
返回的是AsyncTask持有的mHandler,它是与主线程相关的Handler对象
get()方法分析
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
}
注意:它属于FutureTask类中的一个方法
总结
1、AsyncTask是抽象类,无法直接创建对象,由子类创建对象
2、AsyncTask对象必须在主线程中创建,因为AsyncTask类持有的Handler对象必须是主线程中的,这样才能做到线程间的通信
3、我们在堆中创建的每个AsyncTask对象持有的mHandler指向的都是AsyncTask类持有的sHandler对象
4、InternalHandler是AsyncTask中定义的静态内部类,它是扩展了Handler类的子类
5、WorkerRunnable是AsyncTask中定义的静态内部抽象类,它实现了Callable接口
6、AsyncTask是一个范型类,有三个参数类型,<Params, Progress, Result>
7、AsyncTaskResult是AsyncTask中定义的静态内部类,AsyncTaskResult对象负责持有当前AsyncTask对象和一个参数类型为Result的对象
在AsyncTask对象创建前,AsyncTask类加载时做了很多的工作,请参见第一篇文章:加载