Android的AsyncTask異步任務(wù)淺析

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)

  1. Android4.1之前,AsyncTask類必須在主線程中加載。Android4.1之后,沒有了這個(gè)要求,ActivityThread的main方法中自動(dòng)加載了AsyncTask。
  2. 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)代碼
    }
  1. AsyncTask對(duì)象的execute方法必須在主線程中調(diào)用。execute方法有@MainThread注解。
  2. 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");
  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;
}
  1. 內(nèi)存泄漏問題。采用靜態(tài)的AsyncTask繼承類,若要引用外部,采用弱引用。
  2. 使用多個(gè)異步操作并需要進(jìn)行UI變更時(shí),用AsyncTask會(huì)很復(fù)雜,替換Handler會(huì)更靈活。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容