AsyncTask简介
AsyncTask是一种轻量级的异步任务类,它实质上也是对handler和thread做了封装,使用线程池执行后台任务,是一个比较好用的异步类。
AsyncTask的3个参数和4个步骤
3个参数:
params:我们传递给异步任务执行的参数类型;
progress:异步任务在执行的时候,会将执行的进度返回给UI的参数类型;
Result:异步任务执行结束后返回的数据参数类型。
4个步骤:
onPreExecute():这个方法是在执行异步任务之前执行的,通常用来做一些控件的初始化工作,此方法在UI线程中执行。
doInBackground(Params…) :在onPreExecute()方法后执行,这个方法就是在工作线程中执行的,可以做一些相对耗时的任务,在执行的时候,如果调用 publishProgress(Progress... values)方法,可以更新任务的进度,执行结束后,将执行的结果返回给onPostExecute(Result result)处理。
onProgressUpdate(Progress... values):该方法在UI线程中执行,如在异步任务执行时(doInBackground()里面)调用publishProgress()方法,这个方法可以得到返回的进度参数,然后在控件上更新进度条。
onPostExecute(Result result):当异步操作任务执行完成后会将结果返回到这个方法,我们可以将返回的结果显示在控件上,这个方法这是在UI线程上执行的。
AsyncTask的源码分析
上面说了那么多,都是一些很理论的东西,只知道有这么回事儿,但是究竟为什么要这么执行呢?不急,我们从源码的角度来看看吧!
我们知道,要使用AsyncTask,必须先自己定义一个类继承它(假如是MyAsyncTask),然后在主线程中创建这个类,使用MyAsyncTask().execute(params...)来执行,好了基础的代码这里就不贴,重点在源码分析嘛!(注意我这里是基于Android4.4的源码),当我们点到execute这个方法,跳到系统源码类中的:
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
这个方法没什么,只有一个参数sDefaultExecutor,这个参数是啥:
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static final int MESSAGE_POST_RESULT = 0x1;
private static final int MESSAGE_POST_PROGRESS = 0x2;
private static final InternalHandler sHandler = new InternalHandler();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
private final WorkerRunnable<Params, Result> mWorker;
private final FutureTask<Result> mFuture;
private volatile Status mStatus = Status.PENDING;
private final AtomicBoolean mCancelled = new AtomicBoolean();
private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
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实际上就是一个扩展了Executor的SerialExecutor内部类,这里sDefaultExecutor实际上就是一个串行的线程池,也就是说AsyncTask所有的任务在这个线程池中排队执行。这个方法里面,我们主要先看形参Runnable,在try{}语句中有个r.run(),凭直觉,这里应该就是开启线程干活了。这儿先留个伏笔,我们接着往下看:
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;
}
这里我们看到了onPreExecute(),从这也说明了它是在执行异步操作之前先执行的,我们可以看到:onPreExecute()、doInBackground(Params... params)、onProgressUpdate(Progress... values)、onPostExecute(Result result)这几个方法都是protected修饰的,同时public abstract class AsyncTask<Params, Progress, Result>是一个抽象类,所以我们一般是自己写一个类继承AsyncTask,然后子类里面实现这些方法来使用。接着看,这里有2个很重要的成员变量参数,mWorker和mFuture,在看到exec.execute(mFuture)这一行代码的时候,对应前面说的伏笔,那么mFuture这个就是我们要的Runnable对象,r.run(),也就是mFuture干活了。那么这2个这么重要成员变量哪来的呢?接着看:
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
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);
}
}
};
}
这个AsyncTask()实际上是构造函数,在我们创建自己的AsyncTask(MyAsyncTask)的时候,这个类就在UI线程中被调用了。先看看mWorker,这里直接创建了WorkerRunnable<Params, Result>()这个静态抽象的内部类对象,我们看看这是个啥:
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
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;
}
看到最后,发现mWorker是实现了Callable接口的类,这个call()方法,在上面创建的时候实现。再看看mFuture是啥,这里要点到FutureTask类看:
/**
* Creates a {@code FutureTask} that will, upon running, execute the
* given {@code Callable}.
*
* @param callable the callable task
* @throws NullPointerException if the callable is null
*/
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
前面mFuture = new FutureTask<Result>(mWorker)这行代码中,就直接把mWorker传到了FutureTask的成员变量this.callable = callable中的this.callable中。好,看看FutureTask是什么东东:
public class FutureTask<V> implements RunnableFuture<V>
/**
* A {@link Future} that is {@link Runnable}. Successful execution of
* the {@code run} method causes completion of the {@code Future}
* and allows access to its results.
* @see FutureTask
* @see Executor
* @since 1.6
* @author Doug Lea
* @param <V> The result type returned by this Future's {@code get} method
*/
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}
终于看清楚啦,这个mFuture就是咱们需要的Runnable!干活的确定是mFuture了。好我们回过头看看executeOnExecutor方法中的:
exec.execute(mFuture);
这个exec就是传进来的sDefaultExecutor,而sDefaultExecutor我们上面看了,实际就是SerialExecutor类,看看类里面的:
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
第5行r.run();到这里,也就是说执行mFuture.run()了,我们再次看看FutureTask中的run():
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
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 {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
挑重点看,这个方法里把之前创建FutureTask的时候mFuture = new FutureTask<Result>(mWorker)中的mWorker付给Callable<V> c,然后执行result = c.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));
}
};
这个call()方法执行了。仔细看看这个方法里面,return postResult(doInBackground(mParams));终于看到了doInBackgroud了,原来,doInBackground永远执行在Runnable中,也就是说在工作线程中执行,所以我们可以再这里面做一些稍微耗时的工作。当doInBackground返回结果了,我们接着看postResult(doInBackground(mParams)):
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
是不是一种似曾相识的感觉油然而生,这里居然就是使用的handler发送的消息啊!我们看看这个内部类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;
}
}
}
不难看出InternalHandler实际上就是一个Handler,刚才postResult在发送消息时,带的一个参数MESSAGE_POST_RESULT就在这个InternalHandler里的handleMessage方法中处理了。我们接着看
result.mTask.finish(result.mData[0]);
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
finish这个方法很简单,逻辑也很清晰,如果AsyncTask被取消执行了,那么就回调onCancelled(result),否者继续执行onPostExecute(result),这里我们可以了解到需要停止AsyncTask可以在onCancelled(result)这里做处理了。可以看出,doInBackground的返回结果会传递给onPostExecute方法执行,到这里,整个AsycnTask的工作原理就分析完了,不得不佩服老外写程序的思想,简洁的封装了handler和Thread后,就有了这么一个轻量异步处理任务类!