AsyncTask
的原型如下:
package android.os;
public abstract class AsyncTask<Params, Progress, Result> {
...
}
可见,AsyncTask
是抽象类,必须实现它的子类才能使用,下面都是可重写的方法:
@WorkerThread
protected abstract Result doInBackground(Params... params);
@MainThread
protected void onPreExecute() {
}
@MainThread
protected void onPostExecute(Result result) {
}
@MainThread
protected void onProgressUpdate(Progress... values) {
}
@MainThread
protected void onCancelled(Result result) {
onCancelled();
}
@MainThread
protected void onCancelled() {
}
可见,只有doInBackground
方法是必须在子类实现的。由于AsyncTask
一般用在执行后台任务然后更新UI,所以通常至少会重写onPostExecute
方法。当我们在doInBackground
方法中定义好后台任务后,就可以通过execute
方法传入参数:
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
@MainThread
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;
}
在executeOnExecutor
中,会先回调onPreExecute()
做一些准备工作,这是AsyncTask
运行的第一步。然后,后台任务会在exec.execute(mFuture)
中执行,我们先来了解一下这个Executor exec
参数:
package java.util.concurrent;
public interface Executor {
/**
* Executes the given command at some time in the future. The command
* may execute in a new thread, in a pooled thread, or in the calling
* thread, at the discretion of the {@code Executor} implementation.
*/
void execute(Runnable command);
}
Executor
只是一个接口,它用于决定Runnable
怎么执行,线程池类ThreadPoolExecutor
就实现了该接口。在AsyncTask
中,Runnable
默认交给sDefaultExecutor
去执行:
/**
* An {@link Executor} that executes tasks one at a time in serial
* order. This serialization is global to a particular process.
*/
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
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
被赋值为一个串行执行者,这个执行者会将传进来的Runnable
串行执行,就是上一个Runnable
执行完了才执行下一个。这个Runnable
会继续交给线程池THREAD_POOL_EXECUTOR
去执行:
private static final int CORE_POOL_SIZE = 1;
private static final int MAXIMUM_POOL_SIZE = 20;
private static final int KEEP_ALIVE_SECONDS = 3;
/**
* 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,
new SynchronousQueue<Runnable>(), sThreadFactory);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
了解完Executor
,我们再来看看FutureTask<Result> mFuture
,既然它能交给Executor
去执行,显然它是实现了Runnable
接口的。只不过,它是实现了RunnableFuture
接口,而RunnableFuture
接口继承于Runnable
接口:
package java.util.concurrent;
public class FutureTask<V> implements RunnableFuture<V> {
public void run() {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
...
}
}
FutureTask
里的run
方法,会调用Callable
的call
方法。Callable
是一个接口,与Runnable
接口有点类似,不过它的call
方法有返回值,也可以抛出异常:
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*/
V call() throws Exception;
}
FutureTask
的callable
属性可以在构造函数中传入。在AsyncTask
的构造函数中可见,传给FutureTask mFuture
的Callable
是一个WorkerRunnable
对象。WorkerRunnable
是AsyncTask
的内部抽象类,它只是在Callable
的基础上添加了一组属性。
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
现在来看AsyncTask
的构造函数,在初始化过程中,会新建一个WorkerRunnable
对象,在传给FutureTask
:
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);
}
}
};
}
在WorkerRunnable
的call
方法中,可以看到会执行doInBackground
方法,到这里就是是AsyncTask
运行的第二步了。
如果要在后台任务运行过程中,在前台显示进度,则需要在doInBackground
方法里显式调用publishProgress
方法来向UI线程告诉进度:
@WorkerThread
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
private static class AsyncTaskResult<Data> {
final AsyncTask mTask;
final Data[] mData;
AsyncTaskResult(AsyncTask task, Data... data) {
mTask = task;
mData = data;
}
}
由于publishProgress
方法是在后台调用的,所以进度值需要通过Handler
发送给UI线程:
private final Handler mHandler;
private Handler getHandler() {
return mHandler;
}
mHandler
也是在AsyncTask
的构造函数中初始化的,默认情况下,它会绑定到主线程:
private static Handler getMainHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler(Looper.getMainLooper());
}
return sHandler;
}
}
private static class InternalHandler extends Handler {
public InternalHandler(Looper looper) {
super(looper);
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
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;
}
}
}
当mHandler
接收到MESSAGE_POST_PROGRESS
消息时,就会回调AsyncTask
的onProgressUpdate
方法,这是AsncTask
运行的第三步。
在WorkerRunnable
的call
方法中,执行完doInBackground
方法,会调用postResult
方法,该方法与publishProgress
方法类似,都是在后台往主线程发送消息:
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
mHandler
接收到MESSAGE_POST_RESULT
消息时,就会回调AsyncTask
的finish
方法:
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
这里分两种情况,如果后台任务被取消了,会回调onCancelled
方法,否则按正常情况回调onPostExecute
方法。这是AsncTask
运行的第四步。到这里,后台任务也就完成了。