AsyncTask理解:
- AsyncTask是Handler與線程池的封裝初厚。
- 網(wǎng)絡(luò)請求等耗時操作在線程池中完成斥杜,通過handler發(fā)送給主線程完成UI更新针史。
- 使用線程池的主要原因是避免不必要的創(chuàng)建及銷毀線程的開銷痰腮。
AsyncTask的不足:
- 內(nèi)存泄漏問題
- AsyncTask對象必須在主線程中創(chuàng)建,這與內(nèi)部sHandler有關(guān)逝淹,下面會解釋耕姊。
- AsyncTask對象的execute方法必須在主線程中調(diào)用。
- 一個AsyncTask對象只能調(diào)用一次execute方法
Params:doInBackground方法的參數(shù)類型栅葡;
Progress:AsyncTask所執(zhí)行的后臺任務(wù)的進(jìn)度類型茉兰;
Result:后臺任務(wù)的返回結(jié)果類型。
public abstract class AsyncTask<Params, Progress, Result> {
......
}
初始化AsyncTask時欣簇,會對mWorker和mFuture進(jìn)行初始化规脸。mWorker派生自WorkRunnable類的對象坯约。WorkRunnable是一個抽象類,它實現(xiàn)了Callable接口燃辖。在call方法中首先將mTaskInvoked設(shè)為true表示當(dāng)前任務(wù)已被調(diào)用過鬼店,然后設(shè)置線程的優(yōu)先級。調(diào)用了AsyncTask對象的doInBackground方法開始執(zhí)行我們所定義的后臺任務(wù)黔龟,并獲取返回結(jié)果存入result中。最后將任務(wù)返回結(jié)果傳遞給postResult方法滥玷。由此我們可以知道氏身,實際上AsyncTask的成員mWorker包含了AyncTask最終要執(zhí)行的任務(wù)(即mWorker的call方法)。
public AsyncTask() {
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);
}
}
};
}
從上面的分析我們知道了惑畴,當(dāng)mWorker中定義的call方法被執(zhí)行時蛋欣,doInBackground就會開始執(zhí)行,我們定義的后臺任務(wù)也就真正開始了如贷。那么這個call方法什么時候會被調(diào)用呢陷虎?我們可以看到經(jīng)過層層封裝,實際上是mFuture對象封裝了call方法杠袱,當(dāng)mFuture對象被提交到AsyncTask包含的線程池執(zhí)行時尚猿,call方法就會被調(diào)用,我們定義的后臺任務(wù)也就開始執(zhí)行了楣富。下面我們來看mFuture在調(diào)用execute()->executeOnExecutor()的時候被提交到線程池執(zhí)行的凿掂。exec.execute(mFuture);
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
//下面的代碼體現(xiàn)了AsyncTask對象只能調(diào)用execute一次。執(zhí)行execute()時纹蝴,當(dāng)在RUNNING和FINISHED狀態(tài)下都拋出異常
@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;
exec.execute(mFuture);
return this;
}
上述代碼中的sDefaultExecutor是SerialExecutor類庄萎。將待完成的Runnable任務(wù)壓入mTasks的隊列尾部,每次從mTask的頂部拿出Runnable交給THREAD_POOL_EXECUTOR線程池執(zhí)行塘安。
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
sDefaultExecutor是SERIAL_EXECUTOR糠涛,并且用static final修飾,表示一個進(jìn)程中只會初始化一個SERIAL_EXECUTOR兼犯,通過下面的代碼可以知道SerialExecutor線程池的作用用于任務(wù)的排隊忍捡,將任務(wù)交由THREAD_POOL_EXECUTOR執(zhí)行。
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);
}
}
}
mWorker中的call方法會在線程池中執(zhí)行免都,doInBackground執(zhí)行完后锉罐,將結(jié)果傳遞給sHandler。
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
我們知道創(chuàng)建Handler對象時需要當(dāng)前線程的Looper绕娘,為了以后能夠通過sHandler將執(zhí)行環(huán)境從后臺線程切換到主線程(即在主線程中執(zhí)行handleMessage方法)脓规,我們必須使用主線程的Looper。同時sHandler是靜態(tài)變量险领,靜態(tài)變量會在類加載時進(jìn)行初始化侨舆,變相要求在主線程中加載AsyncTask類秒紧。
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
@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;
}
}
}
在MESSAGE_POST_RESULT中,調(diào)用finish方法挨下,如果任務(wù)沒有取消調(diào)用onPostExecute方法熔恢,如果任務(wù)取消調(diào)用onCancelled方法。
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}