問題:
- 為什么一個(gè)AsyncTask只能被執(zhí)行一次?
- 為什么AsyncTask是串行執(zhí)行的, 不能并行嗎?
- 為什么AsyncTask必須在UI線程中創(chuàng)建?
帶著問題看源碼, 穩(wěn).
看一個(gè)源碼當(dāng)然從其構(gòu)造函數(shù)出發(fā).
public AsyncTask(@Nullable Looper callbackLooper) {
// 這里是為什么需要在主線程創(chuàng)建的原因, 不然怎么去更新ui?
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
// WorkerRunnable實(shí)現(xiàn)callable接口并實(shí)現(xiàn)了它的call()方法
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);
}
}
};
}
在這個(gè)構(gòu)造方法里可以看到doInBackground(mParams)
方法, 也就是我們繼承AsyncTask
復(fù)寫的方法. 該方法返回了result
結(jié)果, 最終在finally
里調(diào)用postResult(result);
將結(jié)果通過handler傳遞進(jìn)行處理. 在handler的handleMessage中會調(diào)用AsyncTask
的finish()方法.
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
這里就找到了 onPostExecute(result);
將結(jié)果通過onPostExecute回調(diào)到上層了.
FutureTask
是一個(gè)可管理的任務(wù)類, 它實(shí)現(xiàn)了Runnable和Callable兩個(gè)接口, 稍微瞄一眼源碼可知其可以對Runnable和Callable進(jìn)行包裝.
這里將WorkerRunnable
作為入?yún)鬟f給了FutureTask
.
AsyncTask
還并未開始執(zhí)行, 真正執(zhí)行需要調(diào)用AsyncTask.execute(params);
, 并將params傳遞進(jìn)去.
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
接著看executeOnExecutor(sDefaultExecutor, params);
這里需要看下AsyncTask的三個(gè)狀態(tài):
- PENDING // 等待, 表示任務(wù)未執(zhí)行
- RUNNING // 表示任務(wù)正在運(yùn)行
- FINISHED // 表示任務(wù)已經(jīng)完成結(jié)束
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
// 這里也是為什么一個(gè)AsyncTask只能執(zhí)行一次的原因
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)");
}
}
// 更改為運(yùn)行態(tài)
mStatus = Status.RUNNING;
// 執(zhí)行任務(wù)前調(diào)用onPreExecute()方法, 我們會在onPreExecute進(jìn)行一些不耗時(shí)初始化的操作
onPreExecute();
mWorker.mParams = params;
// 這里開始真正執(zhí)行task任務(wù)
exec.execute(mFuture);
return this;
}
調(diào)用exec.execute(mFuture);
真正執(zhí)行任務(wù)的exec
是什么呢?
是傳遞進(jìn)來的sDefaultExecutor
.
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static class SerialExecutor implements Executor {
// ArrayDeque 先進(jìn)先出的雙端隊(duì)列
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
// 先將任務(wù)都存入隊(duì)列里
// 當(dāng)前沒有執(zhí)行的任務(wù)則從隊(duì)列中取出一個(gè)用THREAD_POOL_EXECUTOR執(zhí)行.
// 當(dāng)前有執(zhí)行的任務(wù)則是在任務(wù)完成后的finally里取出一個(gè)執(zhí)行
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
是一個(gè)靜態(tài)的串行執(zhí)行器, 也就是如果都調(diào)用AsyncTask.execute(params);
方法, 那么一個(gè)進(jìn)程內(nèi)所有AsyncTask都是由sDefaultExecutor
串行執(zhí)行的. 這樣保證一個(gè)時(shí)間只有一個(gè)任務(wù)執(zhí)行.
如果需要并行執(zhí)行任務(wù)則需要調(diào)用executeOnExecutor(Executor exec,Params... params)
另外注意再看看THREAD_POOL_EXECUTOR
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
public static final Executor THREAD_POOL_EXECUTOR;
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;
}
線程池用到了一個(gè)容量128的阻塞隊(duì)列.
到這里我們繼承AsyncTask需要復(fù)寫的方法,就都已經(jīng)在流程中出現(xiàn)了
- onPreExecute()
- doInBackground(params)
- onPostExecute(result)
還有另外一個(gè)onProgressUpdate(progress)
在哪兒呢?
搜索一下源碼.
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
可以在doInBackground()
中調(diào)用publishProgress()
方法來進(jìn)行進(jìn)度的更新. 通過handler來將更新進(jìn)度發(fā)布到UI線程并回調(diào)onProgressUpdate(progress)
方法
AsyncTask的源碼到這里已經(jīng)分析完了, 總的來說難度不大. 最后AsyncTask可能會導(dǎo)致內(nèi)存泄漏, 記得適時(shí)的調(diào)用AsyncTask的cancel()方法
理解記憶關(guān)鍵詞:
handler誓沸、FutureTask(Runnable)合武、SerialExecutor線程池芹敌、主線程初始化