AsyncTask簡單來說就是Android自身提供的一個(gè)簡化后臺讀取數(shù)據(jù),主線程更新UI的幫助類,避免了開發(fā)者自身去實(shí)現(xiàn)Thread和Handler的邏輯。
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
AsyncTask的基本使用就是4個(gè)回調(diào)方法
onPreExecute()
doInBackground(Params... params)
onProgressUpdate(Progress… value)
onPostExecute(Result result)
AsyncTask內(nèi)部使用了一個(gè)SerialExecutor的執(zhí)行器來執(zhí)行任務(wù),從名字就可以看出該執(zhí)行器是串行執(zhí)行任的,如果是通過以下代碼來開啟多個(gè)AsyncTask的執(zhí)行,那么Tasks之間并不是并行的關(guān)系,而是一個(gè)完成之后再繼續(xù)下一個(gè)的串行關(guān)系。
asyncTask.execute(params);
SerialExecutor的實(shí)現(xiàn)
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);
}
}
}
可以看出SerialExecutor每次的execute是先將需要執(zhí)行任務(wù)封裝進(jìn)一個(gè)添加了任務(wù)調(diào)度邏輯的任務(wù)中,并將該任務(wù)添加至隊(duì)列中,最后再根據(jù)當(dāng)前有無正在執(zhí)行的任務(wù)決定是否開啟新一輪的串行任務(wù)執(zhí)行。
如果我們想要多個(gè)AsyncTask并行執(zhí)行應(yīng)該怎么辦呢?
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params)
這是AsyncTask提供的另一個(gè)開啟任務(wù)的方法,該方法是可以指定Executor的,AsyncTask除了SerialExecutor還提供了另一個(gè)執(zhí)行器THREAD_POOL_EXECUTOR,一個(gè) 支持最多128個(gè)待喚醒任務(wù)的并行Executor。
使用一下代碼就可以讓多個(gè)任務(wù)并行執(zhí)行
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,params);
當(dāng)然如果AsyncTask提供的執(zhí)行器不能滿足需求,開發(fā)者還可以定義自己的Executor。
另外AsyncTask有一個(gè)被隱藏的設(shè)置執(zhí)行器的方法,作為內(nèi)部方法使用
/** @hide */
public static void setDefaultExecutor(Executor exec) {
sDefaultExecutor = exec;
}
畢竟如果在多個(gè)AsyncTask執(zhí)行期間調(diào)用該方法來切換默認(rèn)執(zhí)行器的話容易造成Task的調(diào)用混亂。
之前說到AsyncTask的的基本使用就是4個(gè)步驟,并且4步是執(zhí)行在不同的線程的,那這是如何實(shí)現(xiàn)的呢?
簡單描述下就是AsyncTask是通過WorkRunnable, FutureTask, Handler走完自己的基本生命周期的。在execute(params..)或者executeOnExecutor(executor, params...)之后onPreExecute()就會被調(diào)用,緊接著params會傳遞到一個(gè)WorkRunnable實(shí)例中,該實(shí)例和FutureTask的實(shí)例一樣都是在AsyncTask的構(gòu)造函數(shù)中實(shí)例化和初始化的,然后是將包含了該WorkRunnable實(shí)例的FutureTask實(shí)例加入執(zhí)行器中等待執(zhí)行,當(dāng)該任務(wù)被執(zhí)行到時(shí),WorkRunnable會負(fù)責(zé)執(zhí)行doInBackground(params)然后將返回的結(jié)果通過postResult(result)發(fā)送,其實(shí)現(xiàn)就是通過Handler發(fā)送一條狀態(tài)為執(zhí)行完成的消息,Handler處理消息則會根據(jù)當(dāng)前AsyncTask是否已經(jīng)被取消調(diào)用onCancelled(result)或者onPostExecute(result),這樣一個(gè)任務(wù)就執(zhí)行完成了。至于onProgressUpdate(progress)則是在調(diào)用publishProgress(progress)后通過Handler發(fā)送狀態(tài)為更新的消息。
最后關(guān)于AsyncTask的使用有一點(diǎn)需要注意的是它的生命周期比較難確定,即使是調(diào)用了cancel(interrupt = true)方法也不能保證AsyncTask會直接掛掉,所以如果是在Activity等上下文中使用AsyncTask的話就需要注意內(nèi)存泄漏問題,尤其是由于屏幕旋轉(zhuǎn)造成的Activity生命周期變化問題,最好不要使用匿名內(nèi)部類這樣的實(shí)例化方式。
以上基于SDK-24源碼,如有問題請指正。