閱讀78 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Android中的利器-AsyncTask

     在android應用開發過程中,我們需要是時刻注意保證應用程序的穩定和UI操作響應及時,不穩定或響應不及時會帶來不好的用戶體驗。

     那麼為何要引入AsyncTask?

      在Android程序開始運行的時候會單獨啟動一個進程,默認情況下所有這個程序操作都在這個進程中進行。一個Android程序默認情況下隻有一個進程,但一個進程中可以有多個線程。

      在這些線程中,有一個線程叫做UI線程(也叫Main Thread),除了UI線程外的線程都叫子線程(Worker Thread)。UI線程主要負責控製UI界麵的顯示、更新、交互等。因此,UI線程中的操作延遲越短越好(流暢)。把一些耗時的操作(網絡請求、數據庫操作、邏輯計算等)放到單獨的線程,可以避免主線程阻塞。那麼問題來了,如何實現這種異步方式呢?

Android給我們提供了一種輕量級的異步任務類AsyncTask。該類中實現異步操作,並提供接口反饋當前異步執行結果及進度,這些接口中有直接運行在主線程中的(如 onPostExecute,onPreExecute等)。

       就結合AndroidAPI文檔開發文檔解說一下AsyncTask


private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {    
         protected Long doInBackground(URL... urls) {
             int count = urls.length;
             long totalSize = 0;
             for (int i = 0; i < count; i++) {
                 totalSize += Downloader.downloadFile(urls[i]);
                 publishProgress((int) ((i / (float) count) * 100));
                 // Escape early if cancel() is called
                 if (isCancelled()) break;
             }
             return totalSize;
         }
         protected void onProgressUpdate(Integer... progress) {
             setProgressPercent(progress[0]);
         }
         protected void onPostExecute(Long result) {
             showDialog("Downloaded " + result + " bytes");
         }
     }


      

Once created, a task is executed very simply:

 new DownloadFilesTask().execute(url1, url2, url3);

The three types used by an asynchronous task are the following:

  1. Params, the type of the parameters sent to the task upon execution.

//在執行時發送到任務的參數類型。

  2.Progress, the type of the progress units published during the background computation.

//進度,後台計算過程中的進度單位類型,實現進度條,其中publishProgress()中的參數對應onProgressUpdate()中的參數

  3.Result, the type of the result of the background computation.

//此結果是doInBackground返回的結果,而接收的方法為onPostExecute()而result參數即為返回來的參數

  Not all types are always used by an asynchronous task. To mark a type as unused, simply use the type Void:

//異步任務總是使用並非所有類型。 要將類型標記為未使用,隻需使用類型Void:

private class MyTask extends AsyncTask<Void, Void, Void> { ... }1.onPreExecute()在執行任務之前在UI線程上調用。此步驟通常用於設置任務,例如通過在用戶界麵中顯示進度條。

The 4 steps

When an asynchronous task is executed, the task goes through 4 steps:

1.onPreExecute(), invoked on the UI thread before the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.

2.doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.

3.onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.

4.onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.


當執行異步任務時,任務將通過4個步驟:

1.onPreExecute()在執行任務之前在UI線程上調用。此步驟通常用於設置任務,例如通過在用戶界麵中顯示進度條。

2.doInBackground(Params ...),在onPreExecute()完成執行後立即在後台線程上調用。此步驟用於執行可能需要很長時間的後台計算。異步任務的參數被傳遞到此步驟。計算結果必須由此步驟返回,並返回到最後一步。此步驟還可以使用publishProgress(Progress ...)發布一個或多個進度單位。這些值在UI線程上,在onProgressUpdate(Progress ...)步驟中發布。

3.onProgressUpdate(Progress ...),在調用publishProgress(Progress ...)後在UI線程上調用。執行時間未定義。該方法用於在後台計算仍在執行時在用戶界麵中顯示任何形式的進度。例如,它可以用於對進度條進行動畫處理或在文本字段中顯示日誌。

4.onPostExecute(Result),在後台計算完成後在UI線程上調用。後台計算的結果作為參數傳遞給該步驟。


取消任務

任何時候可以通過調用cancel(boolean)來取消任務。調用此方法將導致對isCancelled()的後續調用返回true。調用此方法後,onCancelled(Object),而不是onPostExecute(Object)將在doInBackground(Object [])返回後被調用。為了確保盡快取消任務,您應該始終從doInBackground(Object [])定期檢查isCancelled()的返回值(如果可能的話)。


線程規則

有一些線程規則必須遵循這個類才能正常工作:


必須在UI線程上加載AsyncTask類。自動執行JELLY_BEAN。

必須在UI線程上創建任務實例。

必須在UI線程上調用execute(Params ...)。

不要手動調用onPreExecute(),onPostExecute(Result),doInBackground(Params ...),onProgressUpdate(Progress ...)。

該任務隻能執行一次(如果嚐試第二次執行,將拋出異常)。

記憶可觀察性

AsyncTask保證所有回調調用都是同步的,使得以下操作在沒有顯式同步的情況下是安全的。


在構造函數或onPreExecute()中設置成員字段,並在doInBackground(Params ...)中引用它們。

在doInBackground(Params ...)中設置成員字段,並在onProgressUpdate(Progress ...)和onPostExecute(Result)中引用它們。

執行順序

當首次引入時,AsyncTasks在單個後台線程上串行執行。從DONUT開始,這被更改為允許多個任務並行操作的線程池。從HONEYCOMB開始,任務在單個線程上執行,以避免並行執行引起的常見應用程序錯誤。

如果您真的要並行執行,可以使用THREAD_POOL_EXECUTOR調用executeOnExecutor(java.util.concurrent.Executor,Object [])。

李勝鬆博客

                    

  


最後更新:2017-10-30 10:33:57

  上一篇:go  為了推廣太極文化,馬雲要演電影了
  下一篇:go  你真的會寫Java嗎?