AsyncTask
概述
AsyncTask 是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并在主线程中更新UI。
核心方法
- onPreExecute():在主线程中执行,在异步任务执行之前,此方法会被调用,一般可以用于做一些准备工作。
- doInBackground(Params…params):在线程池中执行,此方法用于执行异步任务,params参数表示异步任务的输入参数。在此方法中可以通过publishProgress方法来更新任务的进度,publishProgress方法会调用onProgressUpdate方法。另外此方法需要返回计算结果给onPostExecute方法。
- onProgressUpdate(Progress…values):在主线程中执行,当后台任务的执行进度发生改变时此方法会被调用。
- onPostExecuter(Result result):在主线程中执行,在异步任务执行之后,此方法会被调用,其中result参数是后台任务的返回值,即doInBackground的返回值。
注意事项
- AsyncTask 的对象必须在主线程中创建。
- execute方法必须在UI线程调用。
- 不能在程序中直接调用onPreExecute、doInBackground、onProgressUpdate、onPostExecuter方法。
- 一个AsyncTask对象只能执行一次,即只能调用一次execute方法,否则会报运行时异常。
使用示例
public class DownloadAsyncTask extends AsyncTask<URL, Integer, Boolean> {
private static final String TAG = "DownloadAsyncTask";
@Override
protected Boolean doInBackground(URL... urls) {
// 根据传进来的url下载文件
......
// 更新下载进度
publishProgress(50);
// 返回下载结果
if (isCancelled()) {
return false;
}
return true;
}
@Override
protected void onProgressUpdate(Integer... progress) {
// 下载进度更新
Log.d(TAG, "progress: " + progress[0].toString());
}
@Override
protected void onPostExecute(Boolean isSuccessful) {
// 下载成功与否
if (isSuccessful) {
Log.d(TAG, "download success");
} else {
Log.d(TAG, "download fail");
}
}
}
// 调用
new DownloadAsyncTask().execute(url);
补充
- onCancelled():在主线程中执行,当异步任务被取消时,onCancelled()方法会被调用,这个时候onPostExecuter则不会被调用。
- execute()与executeOnExecutor()
- 在Android 1.6之前,AsyncTask是串行执行任务的。
- Android 1.6的时候,AsyncTask开始采用线程池处理并行任务。
- 从Android 3.0开始,为了避免AsyncTask所带来的并发错误,AsyncTask又采用一个线程来串行执行任务。
- 在Android 3.0以及后续版本中,可以通过AsyncTask的executeOnExecutor方法来并行地执行任务。
工作原理
-
AsyncTask的继承关系
...... // 先看继承关系,AsyncTask并没有继承什么基类 public abstract class AsyncTask<Params, Progress, Result> { ...... }
-
从构造方法入手
...... public abstract class AsyncTask<Params, Progress, Result> { ...... // 供外部调用的只有下面这个 public AsyncTask() { this((Looper) null); } /** * @hide */ public AsyncTask(@Nullable Handler handler) { this(handler != null ? handler.getLooper() : null); } /** * @hide */ public AsyncTask(@Nullable Looper callbackLooper) { // 构造方法最终调用的构造方法,先是拿到了一个内部的handler mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper() ? getMainHandler() : new Handler(callbackLooper); // 一个Callable mWorker = new WorkerRunnable<Params, Result>() { ...... }; // 一个FutureTask,传参是刚才的那个Callable mFuture = new FutureTask<Result>(mWorker) { ...... }; } ...... }
-
再看execute()方法
...... public abstract class AsyncTask<Params, Progress, Result> { ...... // 外部调用execute() @MainThread public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); } // 最终也是调用的executeOnExecutor() @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; // 线程池任务,传入构造方法中初始化的一个FutureTask exec.execute(mFuture); return this; } @MainThread public static void execute(Runnable runnable) { sDefaultExecutor.execute(runnable); } ...... }
-
从上步看来最后都走的sDefaultExecutor.execute(),所以先来看一下sDefaultExecutor
...... public abstract class AsyncTask<Params, Progress, Result> { ...... public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); ...... private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; ...... 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); } } } ...... }
-
回到第三步提交线程池任务的时候,传参是mFuture,所以再回过头去看mWorker、mFuture
...... public abstract class AsyncTask<Params, Progress, Result> { ...... public AsyncTask(@Nullable Looper callbackLooper) { ...... mWorker = new WorkerRunnable<Params, Result>() { // 相当于run方法里执行的任务,call方法会在线程池中执行 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); } } }; } ...... }
-
最后看一下任务执行完毕后的结果,主要是postResultIfNotInvoked()和postResult()方法
...... public abstract class AsyncTask<Params, Progress, Result> { ...... private void postResultIfNotInvoked(Result result) { final boolean wasTaskInvoked = mTaskInvoked.get(); if (!wasTaskInvoked) { postResult(result); } } private Result postResult(Result result) { @SuppressWarnings("unchecked") // 发消息MESSAGE_POST_RESULT通知,handler默认为一个内部的handler:InternalHandler Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); return result; } ...... private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { // 在主线程处理结果 onPostExecute(result); } // 任务完成 mStatus = Status.FINISHED; } 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: // 调用 finish result.mTask.finish(result.mData[0]); break; case MESSAGE_POST_PROGRESS: // 调用进度更新 result.mTask.onProgressUpdate(result.mData); break; } } } ...... }
参考
[1] 任玉刚.Android开发艺术探索[M].电子工业出版社,2015:507.