轉載 http://oldgrayduck.blogspot.tw/2013/01/androidasynctask-thread.html
AsyncTask (API level 3,所以幾乎所有目前在市面上流通的 Android 版本皆可使用)
是除 Thread 外的另一種選擇,Android 團隊鼓勵主執行緒(UI thread) 專注於操作 & 畫面的流暢呈現,
其餘工作 (如網路資料傳輸、檔案/磁碟/資料存取) 最好都在背景執行;
Thread 通常要搭配 Handler 使用,而 AsyncTask 用意在簡化背景執行 thread 程式碼的撰寫。
如果您預期要執行的工作能在幾秒內完成,就可以選擇使用 AsyncTask,若執行的時間很長,
Android 則強烈建議採用 Executor, ThreadPoolExecutor and FutureTask。
要使用 AsyncTask,必定要建立一個繼承自 AsyncTask 的子類別,並傳入 3 項資料:
Params -- 要執行 doInBackground() 時傳入的參數,數量可以不止一個
Progress -- doInBackground() 執行過程中回傳給 UI thread 的資料,數量可以不止一個
Rsesult -- 傳回執行結果,
若您沒有參數要傳入,則填入 Void (注意 V 為大寫)。
AsyncTask 的運作有 4 個階段:
onPreExecute -- AsyncTask 執行前的準備工作,例如畫面上顯示進度表,
doInBackground -- 實際要執行的程式碼就是寫在這裡,
onProgressUpdate -- 用來顯示目前的進度,
onPostExecute -- 執行完的結果 - Result 會傳入這裡。
除了 doInBackground,其他 3 個 method 都是在 UI thread 呼叫
官方範例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { // 對照前面提到的 3 個傳入的參數 // URL 就是 Params 參數的類別 // Integer 就是 Progress 參數的類別 // Long 就是 Result 參數的類別 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() 以更新 UI 畫面, // 可藉由此方式更新畫面上的進度表 publishProgress(( int ) ((i / ( float ) count) * 100 )); // Escape early if cancel() is called if (isCancelled()) break ; } // 將 totalSize 傳給 onPostExecute() return totalSize; } protected void onProgressUpdate(Integer... progress) { // 這裡接收傳入的 progress 值, 並更新進度表畫面 // 參數是 Integer 型態的陣列 // 但是因為在 doInBackground() 只傳一個參數 // 所以以 progress[0] 取得傳入參數 setProgressPercent(progress[ 0 ]); } protected void onPostExecute(Long result) { showDialog( "Downloaded " + result + " bytes" ); } } |
根據上面的範例,我們要建立一個名為 DownloadFilesTask 的類別,做為下載檔案用,
URL 就是將來會傳入 doInBackground 的變數型態,再看 doInBackground() 這個 method 傳入參數寫法
doInBackgound(URL... urls)
表示傳入的 url 可以不止 1 個。
一旦建立好類別,要執行的方法很簡單:
new DownloadFilesTask().execute(url1, url2, url3);
則 DownloadFilesTask 便會經由 execute() 呼叫 doInBackground(),執行下載 url1, url2, url3 這 3 個檔案,
而 doInBackground() 在處理過程中, 透過呼叫 publishProgress() 來傳送資料給
onProgressUpdate (),onProgressUpdate() 更新畫面上的進度表(如果您有在您的 app UI 顯示進度表的話),
doInBackground() 執行完畢後,會將結果傳給 onPostExecute()。
關於 AsyncTask 的使用,有幾項原則必須遵守:
* AsyncTask 必須在 UI 主執行緒載入. (JELLY_BEAN 版本開始會自動執行此事).
* 必須在 UI 主執行緒建立 AsyncTask.
* 必須在 UI 主執行緒呼叫 AsyncTask.execute().
* 不要自行呼叫 onPreExecute(), onPostExecute(), doInBackground(), onProgressUpdate().
* AsyncTask 只能執行一次.
參考資料 ----
http://developer.android.com/reference/android/os/AsyncTask.html
沒有留言:
張貼留言