前言
AsyncTask是一种异步处理线程的类,他可以在后台处理一些耗时的操作,它相当于Thread线程和handler的合体,为我们更新UI,执行耗时操作,提供方便。
分析源码
AsyncTask中有三个泛型变量,如下:
public abstract class AsyncTask<Params, Progress, Result>
继承自AsyncTask必须重写一个方法,doInBackground(),该方法传入参数是泛型变量Params,返回的是泛型变量Result。它工作在worker线程。
AsyncTask的实例化:
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*
* @hide
*/
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);
}
}
};
}
AsyncTask实例化的过程中,会初始化三个变量,分别是UI处理相关的Handler,用于执行重写方法doInBackground的worker,用于将worker处理后返回数据送到UI处理的future。
在执行doInBackground方法的时候,worker是一个新线程,该线程被设置为后台线程。
我们外部使用的时候,是通过execute(…)来开始执行task.
@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;
}
execute()中可以传递多个参数,也可以不传。首先会判断当前TASK的状态,如果当前task状态为运行或者完成状态,那么task都不会继续往下走。这样是为了保证一个task只会执行一次。
task状态有三种,未运行,运行和结束运行。如下:
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,
}
task必须在UI线程中运行,所以在执行execute方法时候,可以直接调用onPreExecute()方法,来进行前置UI的处理,比如开启进度条。
接下来线程池会开启一个线程来执行初始化时候实例化的feature,feature是一个FutureTask,依据FutureTask的特性,worker只会执行一次,在worker执行完成之后,才会执行接下来的动作。
worker线程不管是否可以正常执行,最后都在执行方法postResult(Result)将结果数据发送给handler,由主UI线程来执行方法onPostExecute(),并将task状态转为完成状态。
FeatureTask重写了done()方法,从源码中看,done方法中执行了
postResultIfNotInvoked(get()),这个方法中判断worker是否正常执行.
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
当发现worker线程没有正常启动执行,那么它会执行最后的方法onPostExecute()来保证流程全部走完。变量wasTaskInvoked在worker初始化的时候会被设为true,之后也没有设为false的选项,所以如果不出意外,是不会执行done()里边的方法的。
task中还有一个方法cancel(),用来终止取消task的执行,查看源码可以看到task通过全局原子布尔变量来控制线程执行取消。
private final AtomicBoolean mCancelled = new AtomicBoolean();
task取消的情况有:
- worker线程执行出现异常,会强制取消终止task的运行
- 用户手动调用cancel方法,此时,会设置该变量为true,同时featuretask也会执行取消执行worker的方法
task取消之后,onPostExecute()方法将不会再执行