Android——AsyncTask源碼分析整理

概述

AsyncTask類內部封裝了Handler和線程池。可以簡化其他線程對UI的操作。

AsyncTask是一個抽象類,我們需要創建子類去繼承它,並且重組一些方法。

參數

  • Params:指定傳給任務執行時的參數的類型

  • Progress:指定後臺任務執行時將任務進度返回給UI線程的參數類型

  • Result:指定任務完成後返回的結果的類型

方法

  • onPreExecute():這個方法在UI線程調用,用於在任務執行前做一些初始化操作,如在界面上顯示加載進度控件

  • doInBackground:在onPreExecute()結束之後立即在後臺線程調用,用於耗時操作。在這個方法中可調用publishProgress方法返回任務的執行進度

  • onProgressUpdate:在doInBackground調用publishProgress後被調用,工作在UI線程

  • onPostExecute:後臺任務結束後被調用,工作在UI線程

源碼

3.0前的AsyncTask

在這裏插入圖片描述

  • 線程池使用的是ThreadPoolExecutor,核心線程數爲5個,最大線程數爲128,非核心線程空閒等待新任務的最長時間爲1s。
  • 阻塞隊列是LinkedBlockQueue,他的容量是10
  • 缺點:線程池最大線程數是128,加上阻塞隊列的10個任務,最多容納138個任務。

3.0後的AsyncTask

這個類的實現,主要有線程池以及Handler兩部分。

構造方法:

在這裏插入圖片描述

  • WorkerRunnable實現了Callable接口,並實現了它的call方法,在call方法中調用了doInBackground(mParams)來處理任務並得到結果,並最終調用postResult將結果投遞出去。
  • FutureTask是一個可管理的異步任務,它實現了Runnable和Futrue這兩個接口。它可以包裝Runnable和Callable,並提供給Executor執行。
  • WorkerRunnable作爲參數傳遞給了FutureTask。

執行一個任務的時候,調用的是execute方法:

public final AsyncTask execute(Params... params){
    return executeOnExecutor(sDefaultExecutor, params);
}
public final AsyncTask 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
    onPreExecute();  
  
    mWorker.mParams = params;  
  
    exec.execute(mFuture);  
    return this; 
} 

概述一下

  • 先檢測任務是否已經執行或者執行結束。然後將任務標記爲running。
  • 開始執行onPreExecute方法。
  • 接着把參數賦值給mWorker對象,他是一個Callable對象,最終會被包裝爲FutureTask。
  • 接下來會調用exec的execute方法,並將mFuture也就是前面講到的FutureTask傳進去。
  • exec是傳進來的參數sDefaultExecutor,它是一個串行的線程池 SerialExecutor,代碼如下

在這裏插入圖片描述
概述一下:

  • 當調用SerialExecutor 的execute方法時,會將FutureTask加入到mTasks中。
  • 當任務執行完或者當前沒有活動的任務時都會執行scheduleNext方法,它會從 mTasks 取出 FutureTask 任務並交由 THREAD_POOL_EXECUTOR 處理。
  • 從這裏可以看出SerialExecutor是串行執行的。註釋2處執行了FutureTask的run方法,它最終會調用WorkerRunnable的call方法。

postReult方法:

在這裏插入圖片描述

  • postResult方法中會創建Message,將結果賦值給這個Message。
  • 通過getHandler方法得到Handler,並通過這個Handler發送消息。

在這裏插入圖片描述
在這裏插入圖片描述
接收到MESSAGE_POST_RESULT消息後會調用AsyncTask的finish方法:

在這裏插入圖片描述

  • 如果AsyncTask任務被取消了,則執行onCancelled方法,否則就調用onPostExecute方法。

線程池SerialExecutor主要用來處理排隊,將任務串行處理。在SerialExecutor中調用 scheduleNext 方法時,將任務交給 THREAD_POOL_EXECUTOR。

THREAD_POOL_EXECUTOR同樣是一個線程池,用來處理任務

在這裏插入圖片描述

  • THREAD_POOL_EXECUTOR 指的就是 threadPoolExecutor,其核心線程和線程池允許創建的最大線程數都是由CPU的核數來計算出來的。
  • 採用的阻塞隊列仍舊是LinkedBlockingQueue,容量爲128。

小結

  • Android 3.0及以上版本用SerialExecutor作爲默認的線程,它將任務串行地處理,保證一個時間段只有一個任務執行;
  • 而Android 3.0之前的版本是並行處理的。
  • Android 3.0之前版本的缺點在Android 3.0之後的版本中也不會出現,因爲線程是一個接一個執行的,不會出現超過任務數而執行飽和策略的情況。
  • 如果想要在Android 3.0及以上版本使用並行的線程處理,可以使用如下的代碼:
    asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");
    
發佈了91 篇原創文章 · 獲贊 63 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章