AsyncTask
概述
AsyncTask被設計成助手類,處理
Handler
和Thread
,但是它並未形成一般的線程框架。AsyncTasks最好運用在短操作場景(最多幾秒種。)
如果你需要使線程運行保持比較長的時間週期,強烈推薦由
java.util.concurrent
提供的其他各種API例如Executor
,ThreadPoolExecutor
和FutureTask
。AsyncTask運行於非主線程,並將結果更新在UI線程。 AsyncTask定義了三個泛型參數
Params
,Progess
,Result
,任務執行主要分爲四步onPreExecute
,doInBackground
,onProgressUpdate
和onPostExecute
。
用法
Async必須繼承使用。子類必須重寫doInBackground
方法,通常也會重寫onPostExecute
。
下面是一個例子:
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");
}
}
子類一旦創建,執行起來非常簡單:
new DownloadFilesTask().execute(url1, url2, url3);
AsyncTask的三個泛型參數
Params
, 任務執行所需要的參數Progress
,後臺任務運行時進度更新的參數Result
,後臺任務結束後的結果參數
並非所有的參數都有作用,如果不需要,刻意簡單的設置爲Void
private class MyTask extends AsyncTask<Void, Void, Void> { ... }
四個步驟
onPreExecute()
,在主線程中執行,執行前任務的初始化,可以更新UI。doInBackground(Params...)
,在非主線程中執行耗時邏輯。在本步中,可以調用publishProgress(Progress...)
更新UI。onProgressUpdate
,在調用publishProgress(Progress...)
方法後在主線程中更新UI。onPostExecute(Result)
,doInBackground(Params...)
執行後在主線程執行。
取消任務
在任何時候,可以通過調用cancel(boolean)取消任務。在調用cancel(boolean) 方法後,調用isCancelled()將返回true,而且在執行完doInBackground(Param...)
後將不執行onPostExecute(Object)
,取而代之的是onCancelled(Object)
。
Threading rules
- AsyncTask**必須**在UI線程中加載。在
JELLY_BEAN
自動完成了此步驟。 - AsyncTask實例必須在UI線程中創建。
- execute(Params…)必須在UI線程中調用。
- 不要人爲調用
onPreExecute()
,onPostExecute(Result)
,doInBackground(Params...)
,onProgressUpdate(Progress...)
。 - 該任務只能執行一次。
Memory observability
AsyncTask確保所有的回調都是同步的,所以以下操作是安全的而不需要顯示同步。
- 在Constructor或者onPreExecute()
設置成員變量,然後在doInBackground()
中引用相關。
- 在doInBackground()
中設置成員變量,然後在onProgressUpdate()
和onPostExecute()
中引用相關。
執行順序
在最初提出,AsyncTask在單後臺線程順序執行。自從DONUT,改爲在一個線程池中多任務並行執行。自從HONEYCOMB,爲了避免由共同應用造成的並行執行錯誤,AsyncTasks在單線程中運行。
如果你確實想要並行執行,你可以調用executeOnExecutor(Java.util.concurrent.Executor,Object[])。