歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android 異步操作AsyncTask

Android 異步操作AsyncTask

日期:2017/3/1 10:34:59   编辑:Linux編程
異步的輕量級實現;
AsynceTask簡述:

1.功能類似於Handler,都是為了防止UI線程操作阻塞而衍生而來。

2.AsyncTask是Handler的一個輕量級實現,模型類似於IntentService於Service。都是為了更加方便操作。(因為一般的異步,我們都是開啟一個子線程或是匿名線程,缺點就是樣的實現對於線程的操作,控制是十分困難)

3.闡述下Handler,一般我們就認為Handler既一個Android消息處理器。默認情況下,他只接受當前線程的消息實例。
但是,當在一個多線程,比如子線程數據處理後更新Ui線程,此時只要存在Handler的指針,簡單的說就是實例對象時,消息的收發處理就能執行在不同的進程中了,這個也是我們常用到的異步處理手法。

4.從源代碼中看AsyncTask類中有 線程池,同樣也實例化了一個Handler對象。
說白了,AsyncTask只是對以上我們自己用handler,thread實現的異步做了一個很好的封裝,使用到線程池對於線程的銷毀和創建開銷大大減小

綜合了下:AsyncTask的異步處理相對於傳統的handler+Thread組合,減少程序中線程過多開銷過大。操作和管理更加方便。

AsyncTask的是實現:
和所有網上說的一樣,該對象必須在UiThread中實例化,然後執行execute方法。
copy下:AsyncTask定義了三種泛型類型 Params,Progress和Result。
•Params 啟動任務執行的輸入參數,比如HTTP請求的URL。
•Progress 後台任務執行的百分比。
•Result 後台執行任務最終返回的結果,比如String。

AsyncTask的執行分為四個步驟,每一步都對應一個回調方法,開發者需要實現一個或幾個方法。在任務的執行過程中,這些方法被自動調用。
onPreExecute(), 該方法將在執行實際的後台操作前被UI thread調用。可以在該方法中做一些准備工作,如在界面上顯示一個進度條。
doInBackground(Params...), 將在onPreExecute 方法執行後馬上執行,該方法運行在後台線程中。這裡將主要負責執行那些很耗時的後台計算工作。可以調用 publishProgress方法來更新實時的任務進度。該方法是抽象方法,子類必須實現。
onProgressUpdate(Progress...),在publishProgress方法被調用後,UI thread將調用這個方法從而在界面上展示任務的進展情況,例如通過一個進度條進行展示。
onPostExecute(Result), 在doInBackground 執行完成後,onPostExecute 方法將被UI thread調用,後台的計算結果將通過該方法傳遞到UI thread.

使用AsyncTask類,以下是幾條必須遵守的准則:
1) Task的實例必須在UI thread中創建
2) execute方法必須在UI thread中調用
3) 不要手動的調用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)這幾個方法

4) 該task只能被執行一次,否則多次調用時將會出現異常


下面是我看了源代碼書寫下整個流程:

step 1:在UiThread中實例化類 執行了父類的構造 ( 代碼都簡寫了)

[java]
  1. public AsyncTask() {
  2. mWorker = new WorkerRunnable{//實現線程接扣的線程類。
  3. public Result call() {
  4. return doInBackground(mParams);//在類似於線程的run方法中調用doInBackground(mParams);
  5. }
  6. };
  7. mFuture = new FutureTask(mWorker) {//接受mWorker線程對象,實例化FutureTask類來操作線程。
  8. }
step 2 :在UiThread中調用AsyncTask對象的execute方法。

[java]
  1. public execute(){
  2. onPreExecute();//此方法中先調用了onPreExecute,也就是我們上文提到的准備工作。
  3. sExecutor.execute(mFuture);// 然後通過線程池操作構造中我們實例化的runnable對象。
  4. return this;
step 3 :根據step 2 可以知道 程序這步執行的應該是mFuture 代碼中的done()

[java]
  1. protected void done() {
  2. Message message;
  3. Result result = null;
  4. // 發送消息Tag和 消息處理結果。消息處理結果又用AsyncTaskResult類封裝起來,實例化對象傳遞進去的result就是上面doInBackground方法執行後的結果。
  5. message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
  6. new AsyncTaskResult<Result>(AsyncTask.this, result));
  7. message.sendToTarget();
  8. }
step 4: 根據step 3,很明顯 handler發送,後緊接著就是消息的處理

[java]
  1. private static class InternalHandler extends Handler {
  2. @Override
  3. public void handleMessage(Message msg) {
  4. AsyncTaskResult result = (AsyncTaskResult) msg.obj;
  5. switch (msg.what) {
  6. case MESSAGE_POST_RESULT://通過step 3的Tag,執行改方法;
  7. // There is only one result
  8. result.mTask.finish(result.mData[0]);
  9. break;
  10. case MESSAGE_POST_PROGRESS:
  11. result.mTask.onProgressUpdate(result.mData);
  12. break;
  13. case MESSAGE_POST_CANCEL:
  14. result.mTask.onCancelled();
  15. break;
  16. }
  17. }
  18. }
step 5: 根據step 4執行 result.mTask.finish

[java]
  1. private void finish(Result result) {
  2. if (isCancelled()) result = null;
  3. onPostExecute(result);// 注意。。執行了onPostExecute
  4. mStatus = Status.FINISHED;
  5. }
至此我們發現上文提到
onPreExecute() ----》doInBackground()------》onPostExecute()基本流程方法都游走一邊


還剩下兩個刷新進度的 : onProgressUpdate()和publishProgress();

[java]
  1. protected final void publishProgress(Progress... values) {
  2. sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
  3. new AsyncTaskResult<Progress>(this, values)).sendToTarget();
  4. }
從這個方法很容易看出,其實他就是一個Handler消息發送的實現。
網上一般說可以在doInBackground()調用該方法,然後再回過去看handler實例化那段代碼
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;


執行了onProgressUpdate()

該類出現了FutureTask以及callable等java中的類。因為手邊沒有java 源碼。沒有細細讀下

整個流程大致如上。

Copyright © Linux教程網 All Rights Reserved