正文
这里 mHandler 被绑定了主线程的 Looper(如果你要用反射质量的方法强行。。。可以绑定子线程 Looper),然后就是一个 WorkerRunnable 和 FutureTask 对象。这两个类是线程相关的概念,不了解的可以去了解一下多线程篇,反正你记住,FutureTask的 run 方法里面会调用WorkerRunnable的 call 方法,所以 mWorker 的 call 方法会在线程池中被调用,也就是异步线程里面被调用。
接下来,我们就从 execute方法被调用开始吧
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
这个方法比较简单,直接调用了executeOnExecutor方法,但是这里有个参数sDefaultExecutor 需要注意一下。先来看这个参数的定义:
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
public static final Executor SERIAL_EXECUTOR = new 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);
}
}
}
从代码中我们可以看到sDefaultExecutor 是一个自定义的静态线程池,注意,是静态的哦,至于里面的逻辑,我们稍后再讲,先来看 executeOnExecutor 方法吧。
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
第一步:这个方法做了状态监测,一旦执行了这个方法 mStatus 状态就不再是 PENDING 了,所以当多次调用 execute 方法多次调用就会异常。
第二步:这个方法调用了onPreExecute 方法,注意,这里没有做任何线程切换,所以onPreExecute 方法回调和 execute 方法是在同一个线程。
第三步:把 params 赋值给mWorker.mParams,这个没什么好说的,大家记得mFuture的 run 方法会调用mWorker的 call 方法即可。
第四步:把构造方法里面的 mFuture 丢进了线程池里面,这个线程池就是刚刚我们说的sDefaultExecutor,现在,我们来看sDefaultExecutor线程池的代码吧。
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);
}
}
}
这里大家可以看到,在execute(final Runnable r)方法里面的参数 r 就是mFuture,然后存到队列 mTask 里面去了,这里代码应该不太好理解,我直接根据结果分析原因了。就是为了保证mTasks队列里面的任务只能“串行”执行,也就是不允许并发。又因为这里是静态资源,独立与某个 AsyncTask,而每个 AsyncTask 的 mFuture又被保存在这里面,等待执行。所以,AsyncTask任务实际上是串行执行的哦。