分析思路
从execute()方法开始分析
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
看到execute()方法接受可变参数,最多可接受三个参数;内部调用了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;
}
这里主要做了几方面的处理:
1. 判断当前要执行的任务的状态,一共三种状态,由Status枚举
public enum Status {
/**
* Indicates that the task has not been executed yet.
*/
PENDING,
/**
* Indicates that the task is running.
*/
RUNNING,
/**
* Indicates that {@link AsyncTask#onPostExecute} has finished.
*/
FINISHED,
}
当任务处于RUNNING状态时,报出异常:提示该任务正在-运行中
当任务处于FINISHED状态时,报出异常:提示该任务已执行过
当任务处于PENDING状态时,可正常执行
- 将当前状态设置为RUNNING状态
- 执行onPreExecute();方法
/**
* Runs on the UI thread before {@link #doInBackground}.
*
* @see #onPostExecute
* @see #doInBackground
*/
protected void onPreExecute() {
}
该方法在doInBackground方法前边执行,可在该方法内初始化一些任务执行需要的信息
4. 调用sDefaultExecutor.execute(mFuture);执行任务
这里有两个变量需要分析:
- sDefaultExecutor
- mFuture
sDefaultExecutor分析
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
/**
* An {@link Executor} that executes tasks one at a time in serial
* order. This serialization is global to a particular process.
*/
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实际上就是一个SerialExecutor,一次只执行一个任务的线程池
mFuture分析
private final FutureTask<Result> mFuture;
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
return postResult(doInBackground(mParams));
}
};
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 occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
mFuture是一个FutureTask实例(FutureTask是一种可以取消的异步的计算任务,有个get方法而获取结果只有在计算完成时获取,否则会一直阻塞直到任务转入完成状态,然后会返回结果或者抛出异常。)
接下来我们查看FutureTask的构造函数:
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
上边创建mFuture时将mWorker作为callable传递进来,接着看mFuture的run()方法
public void run() {
......
......
// 省略部分代码
try {
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);
}
} finally {
......
......
// 省略部分代码
}
}
可以看到内部是调用了callable的call()方法,因此执行sDefaultExecutor.execute(mFuture);方法,实际上就是调用了mWorker的call()方法。接下来我们进入mWorker的call()
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
return postResult(doInBackground(mParams));
}
};
调用了doInBackground()方法
- 这是一个抽象方法,我们需要实现该方法,将需要异步执行的任务放在该方法
- 该方法在异步线程中执行
- 将execute传递进来的参数传递给doInBackground
- 执行完成会返回一个结果Result(传递进来的最后一个参数规定了结果的类型)
通过postResult来通知结果
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
该方法的主要任务是:将执行完成返回的结果封装到Message中,通过sHandler发送出去。那sHandler是什么?做了什么处理?
private static final InternalHandler sHandler = new InternalHandler();
private static class InternalHandler extends Handler {
@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;
}
}
}
可以看到sHandler是一个Handler类型的对象,它主要处理两种消息:
1. MESSAGE_POST_RESULT:执行完成,结束任务
2. MESSAGE_POST_PROGRESS:执行进度,通过onProgressUpdate更新任务进度
接下来跟踪下这两个常量在哪里被调用:
private static final int MESSAGE_POST_RESULT = 0x1;
private static final int MESSAGE_POST_PROGRESS = 0x2;
MESSAGE_POST_PROGRESS
搜索发现,只在publishProgress方法中用到,在这里通过sHandler发送该类型的消息
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
因此在需要更新状态的时候,我们需要调用publishProgress方法(参数为当前任务的进度);这样就会通知主线程执行onProgressUpdate方法,就可以在该方法中执行UI更新等
MESSAGE_POST_RESULT
在postResult()方法中有用到,当doInBackground执行结束后,会通知结束任务:result.mTask.finish(result.mData[0]);该方法主要是调用了AsyncTask的finish方法
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
这里主要做了两个操作:
1. 假如任务被取消,则调用onCancelled(result);方法;假如任务没被取消,则调用onPostExecute(result);方法
2. 将当前任务的状态设置为FINISHED
总结
1 AsyncTask方法
从上边的流程可以知道,在使用AsyncTask时主要涉及到以下几个方法:
1. onPreExecute():doInBackground之前执行,在主线程执行,用于初始化信息等
2. doInBackground():抽象方法,需要实现具体的操作,在子线程执行
3. publishProgress():发布任务当前进度,当调用该方法时,onProgressUpdate()方法会被调用
4. onProgressUpdate():在主线程执行,可在该方法内更新UI
5. onPostExecute():主线程执行,返回任务执行的结果
2 注意事项
- AsyncTask只能被执行一次,要不会报出异常
- 需要在主线程调用execute()方法