Android的AsyncTask異步任務(wù)淺析
實(shí)現(xiàn)原理
內(nèi)部封裝了2個(gè)線程池+1個(gè)Handler(InternalHandler),1個(gè)線程池SerialExecutor任務(wù)排隊(duì),一個(gè)線程池THREAD_POOL_EXECUTOR執(zhí)行任務(wù)。
常用重寫的方法
- onPreExecute:運(yùn)行在主線程中,可做UI更新,顯示進(jìn)度條通知等。
- doInBackground:在子線程執(zhí)行任務(wù),接收的參數(shù)類型為AsyncTask第一個(gè)泛型,返回給onPostExecute的參數(shù)類型為AsyncTask第三個(gè)泛型。
- onProgressUpdate:運(yùn)行在主線程中,doInBackground中調(diào)用publishProgress方法后即可回調(diào)到該方法中,用于UI進(jìn)度更新。接收的參數(shù)類型為AsyncTask第二個(gè)泛型。
- onPostExecute:運(yùn)行在主線程中,doInBackground任務(wù)執(zhí)行完畢后,就會(huì)回調(diào)到該方法中。
- onCancelled:調(diào)用AsyncTask的cancel方法時(shí),會(huì)回調(diào)到該方法中,內(nèi)部調(diào)用Thread的interrupt方法,告訴線程池要取消任務(wù),Thread在合適時(shí)機(jī)取消任務(wù)。
public class MyTask extends AsyncTask<String, Double, Float> {
@Override // 子線程執(zhí)行任務(wù)
protected Float doInBackground(String... strings) {
publishProgress(5D);
return 1f;
}
@Override // 準(zhǔn)備執(zhí)行doInBackground任務(wù)時(shí)回調(diào)
protected void onPreExecute() {
super.onPreExecute();
}
@Override // doInBackground任務(wù)執(zhí)行結(jié)束后回調(diào),接收的參數(shù)為doInBackground返回的值
protected void onPostExecute(Float aFloat) {
super.onPostExecute(aFloat);
}
@Override // doInBackground調(diào)用publishProgress會(huì)回調(diào)到該方法中
protected void onProgressUpdate(Double... values) {
super.onProgressUpdate(values);
}
@Override // 調(diào)用AsyncTask的任務(wù)關(guān)閉后回調(diào)
protected void onCancelled() {
super.onCancelled();
}
}
注意事項(xiàng)
- Android4.1之前,AsyncTask類必須在主線程中加載。Android4.1之后,沒有了這個(gè)要求,ActivityThread的main方法中自動(dòng)加載了AsyncTask。
- AsyncTask對(duì)象要在主線程創(chuàng)建,創(chuàng)建時(shí),AsyncTask構(gòu)造方法中,會(huì)拿到當(dāng)前線程的Looper,傳給new的Handler實(shí)例,以保證Handler是在主線程中。
public AsyncTask(@Nullable Looper callbackLooper) {
// 創(chuàng)建AsyncTask對(duì)象時(shí),若不傳外部的Handler實(shí)例,會(huì)走到這個(gè)構(gòu)造中
// 拿到當(dāng)前線程的Looper,傳給new的Handler,則Handler在當(dāng)前創(chuàng)建AsyncTask對(duì)象的線程中
// 因此,若要保證Handler執(zhí)行環(huán)境在主線程,必須要在主線程中創(chuàng)建AsyncTask對(duì)象
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
......省略無關(guān)代碼
}
- AsyncTask對(duì)象的execute方法必須在主線程中調(diào)用。execute方法有@MainThread注解。
- Android3.0之前AsyncTask調(diào)execute方法是并行執(zhí)行任務(wù),3.0之后增加了SerialExecutor線程池,默認(rèn)選擇該線程池串行執(zhí)行任務(wù),若想并行執(zhí)行,則直接調(diào)executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params)方法即可。
MyTask myTask = new MyTask();
// 默認(rèn)在SerialExecutor線程池中串行執(zhí)行
myTask.execute("1");
// 并行執(zhí)行
myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "1");
- 一個(gè)AsyncTask對(duì)象,只能執(zhí)行一次execute方法,第二次執(zhí)行就會(huì)拋異常。
@MainThread // 主線程中執(zhí)行的方法,默認(rèn)選擇SerialExecutor線程池串行執(zhí)行任務(wù)
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
@MainThread // 主線程中執(zhí)行的方法。外部也可直接調(diào)這個(gè)方法執(zhí)行任務(wù),自己傳入線程池選擇是串行還是并行。
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
// 一個(gè)AsyncTask對(duì)象,若多次執(zhí)行execute,走到這里,會(huì)判斷任務(wù)在執(zhí)行中或已結(jié)束時(shí),都將拋異常
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;
}
- 內(nèi)存泄漏問題。采用靜態(tài)的AsyncTask繼承類,若要引用外部,采用弱引用。
- 使用多個(gè)異步操作并需要進(jìn)行UI變更時(shí),用AsyncTask會(huì)很復(fù)雜,替換Handler會(huì)更靈活。