1 AsyncTask简介
AsyncTask<Params, Progress, Result>
- Params:启动任务执行的输入参数,如doInBackground的输入参数
- Progress:后台任务执行的百分比,如on
- Result:后台任务执行最终返回的结果,比如doInBackground返回值类型以及onPostExecute的输入参数。
- execute(Params... params):执行一个异步任务,需要我们手动去调用此方法,触发异步任务的执行。
- onPreExecute():在execute(params... params)被调用后立即执行,一般用来在执行后台任务前做一些准备工作。
- doInBackground(Params... params):在onPreExecute()完成后立即执行,用于执行耗时操作,在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。
- onProgressUpdate(Progress... values):在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。
- onPostExecute(Result result):当后台操作结束时,此方法将会被调用,计算结果将作为参数传递到此方法中,直接将结果显示到UI组件上。
2 AsyncTask执行流程
按照AsyncTask执行顺序来,AsyncTask构造方法--->execute--->onPreExecute--->doInBackground、onProgressUpdate()--->onPostExecute
- AsyncTask初始化时会初始化一个Handler、WorkRunnable和FutureTask对象,该Handler默认调用的是主线程的Looper,WorkRunnable实现了Callable接口
- AsyncTask是用线程池来执行任务的。在调用execute方法时,会调用onPreExecute,然后调用ThreadPoolExecutor的execute方法来执行FutureTask,而WorkRunnable被传入到FutureTask中,因此会调用WorkRunnable里面的call方法。
- 在WorkRunnable里面的call方法中会执行doInBackground方法,且call方法最终会调用postResult方法,该方法中将最终结果封装到Message中,然后通过Message.sendToTarget最终将消息传入到消息队列中。
- Looper从MessageQueue中取出消息交给Handler处理,然后根据需求调用onPostExecute和onProgressUpdate。
2.1 AsyncTask构造方法
public AsyncTask() {
this((Looper) null);
}
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);
}
}
};
}
这里实例化了一个Handler,WorkerRunnable和FutureTask对象,WorkerRunnable对象实现了Callable接口,如果没有指定Looper,则使用的是主线程的Looper
2.2 execute
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
private volatile Status mStatus = Status.PENDING;//默认没有被执行
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;
}
分析:调用execute方法时,会调用executeOnExecutor方法,该方法传入了两个参数,其中一个是sDefaultExecutor,该sDefaultExecutor被实例化为SerialExecutor对象。在executeOnExecutor方法里,首先判断AsyncTask状态,AsyncTask默认状态是未被执行,如下所示,AsyncTask状态有以下几种:
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,
}
2.3 onPreExecute
在executeOnExecutor判断,如果AsyncTask没有被执行,则执行接下来的操作;如果被执行了,则抛出异常。如果AsyncTask没有被执行,则将状态设置为运行中,并调用onPreExecute()方法,该方法是一个空的方法,具体内容需要自己重写,而且它是运行在主线程中的。
@MainThread
protected void onPreExecute() {
}
2.4 doInBackground
在executeOnExecutor里,接下来继续执行,将execute传入的参数存放在mWorker.mParams中,mWorker是WorkerRunnable对象,实现了Callable接口,这里可以参考【线程创建的四种方式】中使用Callable和Future来创建线程。这里有些许不同,这里是通过线程池来加载FutureTask的。接下来执行exec.execute(mFuture);exec是executeOnExecutor传入的第一个参数,是SerialExecutor对象。所以调用的是SerialExecutor里的execute方法
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);
}
}
}
该方法会将FutureTask存入一个双端数组队列中,然后从队列中取出FutureTask并交给threadPoolExecutor执行,关于线程池可以参考【Android 线程池原理及使用】
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
当线程池执行时,就会执行FutureTask,FutureTask会先执行WorkerRunnable的call方法,在call方法中调用doInBackground方法
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;
}
};
当doInBackground执行完后,会调用postResult
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
在postResult中,会通过message.sendToTarget()将详细发送到MessageQueue中存储,接下来就是消息机制了,MessageQueue接收到消息后会将Message存入到消息队列中,然后如果Looper被阻塞,则唤醒Looper,Looper被唤醒后会无限循环从MessageQueue中取出消息,然后将取出的消息通过msg.target.dispatchMessage发送给执行的Handler进行处理,然后handler调用handleMessage处理消息,这段可参考【Android消息机制】
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;
}
}
}
如上述代码所示,msg.what=MESSAGE_POST_PROGRESS时,调用onProgressUpdate方法,msg.what=MESSAGE_POST_RESULT时调用finish方法,该finish方法中将结果返回给onPostExecute方法
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
2.5 onPostExecute
onPostExecute方法是一个空方法,需要自己重写
protected void onPostExecute(Result result) {
}
3 流程总结
- AsyncTask初始化时会初始化一个Handler、WorkRunnable和FutureTask对象,该Handler默认调用的是主线程的Looper,WorkRunnable实现了Callable接口
- AsyncTask是用线程池来执行任务的。在调用execute方法时,会调用onPreExecute,然后调用ThreadPoolExecutor的execute方法来执行FutureTask,而WorkRunnable被传入到FutureTask中,因此会调用WorkRunnable里面的call方法。
- 在WorkRunnable里面的call方法中会执行doInBackground方法,且call方法最终会调用postResult方法,该方法中将最终结果封装到Message中,然后通过Message.sendToTarget最终将消息传入到消息队列中。
- Looper从MessageQueue中取出消息交给Handler处理,然后根据需求调用onPostExecute和onProgressUpdate。
4 细节
- AsyncTask的execute方法每次只能执行一次
- 使用的线程池,则可以复用线程池里的线程,减少了开销,提升了性能
网友评论