Android中處理耗時操作時,我們常常使用AsynckTask來處理,那AsynckTask的是怎樣執行的呢?我們探究一下源碼。
一、AsynckTask的主要的四個方法
- onPreExecute()任務執行開始前,主線程中
- doInBackground()AsynckTask的抽象方法,任務執行中,在子線各執行
- onProgressUpdate()執行中,主線程中
- onPostExecute()執行完成,在主線程中
二、探究源碼
AsynckTask的執行起點是execute方法,
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
上面的sDefaultExecutor是一個線程池,在類新建的時候初始化,相關代碼
//線程池
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
//execute方法中sDefaultExecutor
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
//r爲下文中的mFuture
public synchronized void execute(final Runnable r) {
//可以理解爲任務的調度
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
//任務真正執行的地方,mWorker是在THREAD_POOL_EXECUTOR線程池中執行的
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
接下來進行到executeOnExecutor方法中,這個方法的源碼如下:
//判斷此任務的狀態,如果不是初始狀態,拋出異常,這也是異步任務在執行過程中,不能重複執行的原因,一個異常任務只能執行一次,想再次執行得再new
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,主線程中
onPreExecute();
//參數傳遞
mWorker.mParams = params;
//放在上文中的sDefaultExecutor去執行下一步
exec.execute(mFuture);
return this;
上面的方法,mWorker與mFuture是什麼呢?這兩個是在異步任務創建時,初始化的
public AsyncTask() {
//任務執行線程
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
//AtomicBoolean標誌位,設置爲true,
mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//參數傳遞並在子類執行doInBackground方法,此方法必須執行
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);
}
}
};
}
//判斷mWorker的狀態,如果mTaskInvoked.get()爲false,表示doInBackground方法已執行完
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
}
//如果執行完,使用Handler發送信息到主線程進行下一步處理
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
下面來看一下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:
// 執行fisish方法,如果任務沒有被取消,將會執行onPostExecute,並返回數據
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
// onProgressUpdate方法執行 result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
那onProgressUpdate會在什麼時候執行呢,當我們調用下面方法將會執行
protected final void publishProgress(Progress... values) {
//如果任務沒有取消,發送消息
if (!isCancelled()) {
sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
後記:大部分的註釋解析已寫到代碼中。可能組織的不好,希望請見諒。Thanks,:)