我们在有异步任务时经常会使用 AsyncTask,都知道是 Handler + 线程池的异步框架,那原理是什么呢?怎么做到按顺序执行 onPreExecute() doInBackground() 等方法的呢,本篇文章会回答这些问题。
下面从构造方法开始看
public AsyncTask() {
this((Looper) null);
}
public AsyncTask(@Nullable Handler handler) {
this(handler != null ? handler.getLooper() : null);
}
AsyncTask 最终会执行到下面这个构造方法
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);
}
}
};
}
可以看到在构造方法里,赋值了三个成员变量 mHandler,mWorker,mFutre。我们一个一个来分析
Handler
public AsyncTask(@Nullable Looper callbackLooper) {
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
如果当构造方法里的 callbackLooper 为 null 或者该 lopper 是在主线程中,mHandler 为主线程的 Handler ,否则就是该 Looper 所在线程的 Handler。
然后来看 mWorker,它是一个 WorkerRunnable
WorkerRunnable
WorkerRunnable 是什么呢
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
是实现了 Callable 接口的抽象类
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;
}
};
并重写了 call() 方法
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
Callable 接口和 Runnable 接口一个很大的区别就是 Callable 接口有返回值
再看 mFutrure,它是 FutureTask 类
FutureTask
public class FutureTask<V> implements RunnableFuture<V> {
FutureTask 类实现了 RunnableFuture接口
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}
RunnableFuture 又继承了 Runnable 和 Future 接口
Runnable 接口只有一个 run() 方法我们都知道
Future 接口的部分注释说明如下
A {@code Future} represents the result of an asynchronous
* computation. Methods are provided to check if the computation is
* complete, to wait for its completion, and to retrieve the result of
* the computation. The result can only be retrieved using method
* {@code get} when the computation has completed, blocking if
* necessary until it is ready. Cancellation is performed by the
* {@code cancel} method. Additional methods are provided to
* determine if the task completed normally or was cancelled. Once a
* computation has completed, the computation cannot be cancelled.
* If you would like to use a {@code Future} for the sake
* of cancellability but not provide a usable result, you can
* declare types of the form {@code Future<?>} and
* return {@code null} as a result of the underlying task.
注释说明了 Future 接口是可以获取异步任务执行结果的,也可以判断当前任务状态以及取消任务等操作。提供了 cancel() get() isCanceled() idDone() 等方法
再来看给 mFuture 赋值的地方
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);
}
}
};
在 new 的时候把 mWorker,即上面的 Callable 传入作为构造参数,并且重写了 done() 方法
来看构造方法对 Callable 做了什么
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
仅仅是将 callable 赋值,并在 FutureTask 的 run() 中执行 callable.call()
public void run() {
...
try {
//使用构造函数中的 callable
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
//执行 callable
result = c.call();
ran = true;
}
...
所以当运行 FutureTask 的run()时,也就执行了前面 mWorker 的 callable
并且重写了 done() 方法,先看下 FutureTask 中的 done() 方法
/**
* Protected method invoked when this task transitions to state
* {@code isDone} (whether normally or via cancellation). The
* default implementation does nothing. Subclasses may override
* this method to invoke completion callbacks or perform
* bookkeeping. Note that you can query status inside the
* implementation of this method to determine whether this task
* has been cancelled.
*/
protected void done() { }
是一个空实现,注释中也说明了当任务执行完毕或者被取消后会调用该方法,mFuture 的 done() 执行的内容后面再分析;至此 AsyncTask 的构造方法分析完毕了,然后分析运行时执行的 execute() 方法。
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
//检查 status,只能运行一次
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()
onPreExecute();
mWorker.mParams = params;
//调用 executor 的 execute()
exec.execute(mFuture);
return this;
}
在 execute() 方法我们看到先对状态进行检查,然后调用onPreExecute(),并调用 exec.execute(mFuture);
exec 是 sDefaultExecutor,sDefaultExecutor 是SerialExecutor实例,我们来看这个类
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
//添加 Runnable 到 mTasks 的队尾
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
//用线程池执行 mTasks 中的 Runnable
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
他的 execute(Runnable r)传入的参数是 mFuture 这个 Runnable,
mTasks是明显是一个队列,mTasks.offer(Runnable r) 做的是将 runnable 添加到队尾。所以 execute() 将传进来的 mFuture 再封装成 Runnable,然后用线程池执行 mTasks 中的 Runnable。然后我们再来看这个线程池
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// We want at least 2 threads and at most 4 threads in the core pool,
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
/**
* An {@link Executor} that can be used to execute tasks in parallel.
*/
public static final Executor THREAD_POOL_EXECUTOR;
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
AsyncTask 创建了一个线程池,核心线程最多为4个,最大队列长度为128,当用线程池执行 execute 时,就开始了真正的后台任务。
至此我们小结一下,线程池 execute(runnable) 的 Runnable 即为经过封装的 FutureTask,前面看了 FutureTask 的 run() 又会调用 callable 的 call(), callable 是创建 FutureTask的参数,即 mWorker。所以也就是运行了 mWorker 的call(),我们把代码再复制过来看
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;
}
};
这里看到调用了 doInBackground() ,并在 finnaly 执行了 postResult() 做完成后的操作
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
看到是用 handler 发送了一条 MESSAGE_POST_RESULT 的消息,再看 handler 的 handleMessage 怎么处理的
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
对 MESSAGE_POST_RESULT 的处理是调用 mTask 的 finish(),mTask 为 AsyncTask 本身。
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
很清晰的表明了是否是取消,如果是执行完毕就调用我们重写的 onPostExecute()。
至此还没完,到这儿执行完了 mWorker 的 call(),这是由 FutureTask 调用的,FutureTask 还有自己执行完调用的方法,done()
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);
}
}
};
执行的是 get() 返回值,然后调用 postResultIfNotInvoked()
get() 会阻塞线程直到执行完毕返回。所以当执行完毕或者取消时才会执行 postResultIfNotInvoked()
private void postResultIfNotInvoked(Result result) {
//获取 mTaskInvoked 是否被 set
final boolean wasTaskInvoked = mTaskInvoked.get();
//如果没被 set true 就执行 postResult 结束
if (!wasTaskInvoked) {
postResult(result);
}
}
上面我们看到是在 worker 的 call() 对 mTaskInvoked set 值的;
所以当任务被取消时才会调用到这里,postResult 即 call() 的 finally 执行的结束任务,调用 postExecute() ;到这里就是 Asynctask 的整体执行流程源码分析了。
再补充一个在过程中更新的过程,我们在需要更新时会调用 publishProgress()
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
我们看到也是用 handler 发送了一条消息,在 handleMessage 中处理
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
做的是调用我们重写的 onProgressUpdate(),因为 handler 是在 UI 线程中的,所以我们的 onPostExecute() 和 onProgressUpdate() 都可进行 UI 更新的操作。