AsyncTask原理

AsyncTask 異步執行

AsyncTask 中持有了靜態的 InternalHandler (初始化時默認綁定 MainLooper),靜態的串行執行任務的線程池和靜態的並行執行任務的線程池

但是串行執行任務的線程池並不會自己處理任務,而是調用並行線程池處理任務。執行任務時將任務添加到串行線程池中的 mTask 隊列中,隊列中會依次取出任務並調用並行線程池來執行任務,在傳遞任務時通過 WorkderRunnable 和 FutureTask 將參數傳遞到並行線程池,並行線程池中處理任務時調用 doInBackground 方法,該方法執行在子線程。

並行線程池每執行完一個任務, 都會通過 InternalHandler 發送消息,InternalHandler 處理消息在主線程,收到執行完成消息後,做完成處理(消息中持有當前 AsyncTask 對象的引用,調用該引用完成操作)。

執行結束後串行線程池會從隊列中再取出一個任務,如果沒有任務則不處理,有任務則繼續調用並行線程池處理,所以串行線程池中通過 mTask 隊列完成串行執行。

執行流程分析

AsyncTask

InternalHandler

構造函數中默認綁定 MainLooper ,其處理消息在主線程

SerialExecutor sDefaultExecutor 串行執行任務的線程池

Executor THREAD_POOL_EXECUTOR 並行執行任務的線程池

  1. AsyncTask 初始化時,初始化 FutureTask 對象,爲一個 Runnable,其保持了 WorkerRunnable 對象的引用,WorkerRunnable 中持有任務參數。

  2. excute 方法中,調用了 ExcuteOnExecutor 方法, 將 SerialExecutor 作爲默認線程池處理 FutureTask 任務

  3. ExcuteOnExecutor 會先判斷當前異步任務的狀態,如果在運行或結束則拋出異常,無異常則修改 AsyncTask 的狀態並執行 onPreExcute 方法,接着調用 SerialExecutor 的 execute 方法

  4. SerialExecutor 的 execute 方法將任務添加到其內部的隊列 mTasks 中,按順序依次執行

  5. SerialExecutor 中執行任務時,調用 THREAD_POOL_EXECUTOR 處理任務,執行完畢後再從 mTasks 中取下一個任務,從而實現串行

  6. 執行任務時在子線程中,調用被執行的 FutureTask 的 run 方法,其中調用其保持的 WorkerRunnable 對象的 call 方法

  7. call 方法中,會調用 doInBackground 方法從而該方法中的代碼執行在子線程,調用 publishProgress 方法通過 InternalHandler 消息機制向主線程發送進度

  8. call 方法中 doInBackground 執行結束後,調用 postResult 方法,通過消息機制,調用 AsyncTask 的 finish 方法

  9. finish 方法中判斷如果任務取消則調用 onCancelled 如果未取消則調用 onPostExecute ,最後更新任務的狀態

總結

  1. 1.6 版本之前串行處理,1.6之後並行處理,3.0之後再次改爲串行處理,想要並行執行,直接調用 executeOnExecutor 方法,參數傳入 AsyncTask 的靜態屬性 THREAD_POOL_EXECTOR 線程池。

  2. 創建 AsyncTask 類對象,調用 execute 方法啓動,默認啓動的是順序執行的,執行過程中線程的切換是通過靜態的 InternalHandler 完成的

  3. InternalHandler 創建時自動綁定 MainLooper ,所以處理事件運行在主線程

  4. AsyncTask 實例化時,會創建創建 WorkerRunnable 對象和 FutureTask 對象,在線程池中的線程運行時會在 FutureTask 的 run 方法中調用 WorkerRunnable 的 call 方法,call 方法就運行在了子線程,call方法中調用 doInBackground 方法也就運行在了子線程

  5. doInBackground 執行結束之後會使用 InternalHandler 發消息將當前 AsyncTask 和 返回值傳遞到主線程

  6. 主線程處理消息時調用對應 AsyncTask 的 finish 方法,處理 onCanclelled 和 onPostExecute 方法

  7. 子線程運行過程中的進度提交也是通過類似方式,在 doInBackground 中調用 publishProgress 方法,該方法會將進度使用 InternalHandler 提交

  8. 主線程收到 InternalHandler 發來的進度之後,通過 onProgressUpdata 接收進度並做相應處理

  9. 運行時首先調用 opRreExecute 方法,再通過 Executor 的 excute 方法,將包裝了 WorkerRunnable 這個 Runnable 對象的 FutureTask 對象傳入線程池,線程池中就會調用 FutureTask 的 run 方法,run 方法中調用 WorkerRunnable 的 call 方法,call 再執行 doInBackGround 方法,最後通過 Handler 提交到主線程執行 onPostExcuete 方法

發佈了28 篇原創文章 · 獲贊 9 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章