AsyncTask是异步任务,在不阻塞UI线程的情况下,在后台处理复杂逻辑,并将结果返回到UI线程,现在来分析一下AsyncTask的实现。
先来看看我们常见的使用方法。
先声明一个类,继承自AsyncTask。
class MyTask extends AsyncTask<Void,Integer,Integer>{
@Override
protected Integer doInBackground(Void... params) {
// TODO Auto-generated method stub
return null;
}
}
然后使用它
MyTask task;
task = new MyTask();
task.execute();
具体
AsyncTask都做了什么,一步步看。在
AsyncTask内部有两个很重要的对象
private final WorkerRunnable<Params, Result> mWorker;
private final FutureTask<Result> mFuture;
先看看WorkerRunnable
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
WorkerRunnable继承自Callable,Callable的官方说明是:Callable和Runnable类似,都是可以在另一个线程中执行的,但是二者还是有区别的。
1、Callable的接口方法是call,Runnable是run
2、Callable可以带返回值,Runnable不行
3、Callable可以捕获异常,Runnable不行
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;
}
再看看FutureTask,FutureTask是异步计算的结果,继承关系是 FutureTask -> RunnableFuture->Runnable, Future,FutureTask内部可以判断任务的执行状态,并切可以取消任务。
FutureTask的构造函数接收一个Callable类型参数,赋值给callable对象
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
上面的WorkerRunnable被传入,在FutureTask的run方法中,调用WorkerRunnable的call方法执行,并返回结果。
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) {
......
}
if (ran)
set(result);
}
} finally {
......
}
}
下面就来看看AsyncTask的初始化
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
......
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
......
}
};
}
我们
看到,之前提到过的两个对象,在这里被创建,mFuture实现了done的重载,就是任务完成后,执行此处代码。当我们执行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) {
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;
}
通过 exec.execute(mFuture); 开始执行任务,
execute需要Runnable类型对象,mFuture就是FutureTask类型对象,继承自Runnable。
再看看结果获得后,返回的动作。
在FutureTask中的run方法中通过 callable 开始执行任务,任务结束后,会执行set方法
public void run() {
......
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
......
if (ran)
set(result);
}
} finally {
......
}
}
set方法中执行结束任务的方法 finishCompletion,这里就会调用 done 接口,就通知到了AsyncTask的mFuture的done回调
protected void set(V v) {
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = v;
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}
private void finishCompletion() {
// assert state > COMPLETING;
......
done();
callable = null; // to reduce footprint
}
mFuture的done回调中会通过postResultIfNotInvoked调用postResult直接提交结果,那么对于另一个对象mWorker来说,在call回调中,通过postResult(doInBackground(mParams));去提交结果,所以 doInBackground 是我们必须实现的一个接口函数。
postResult中通过内部的一个handler,去通知UI进程,并处理 onPostExecute 及 onProgressUpdate 接口的实现。这样就完成了任务的整个传递。