Android AsyncTask-耗時工作設計

作者 | 2016-03-26

Android應用程式中若想設計網路連線的程式功能,除了Java原本就有的Thread、Executor等類別外,可使用AsyncTask類別

UI執行緒與耗時工作

應用程式在手機上執行時,主要負責與使用者互動,在執行並與使用者互動的過程,是以一個專屬的執行緒進行,這個執行緒稱為「UI thread」或「main thread」,如下圖,假設橫向箭頭是UI執行緒,從開始到應用程式結束,由同一個執行緒負責與使用者互動:

A4252-1

耗時工作處理-AsyncTask類別

在Android應用程式中若想設計網路連線的程式功能,除了Java原本就有的ThreadExecutor等類別外,可使用AsyncTask類別,在字義上,Async是非同步「Asynchronized」的簡寫,它允許開發人員設計能在背景執行的工作,並提供方法能夠與UI thread溝通互動,適合進行較短時間(數秒)的耗時工作,它的運作如下圖:

A4253

上圖在執行過程中啟動一個AsyncTask進行耗時工作,而原本的UI thread(橫向箭頭)仍然在耗時工作執行過程中可以讓元件與使用者互動。

設計AsyncTask

1. 設計AsyncTask的子類別並訂定規範

設計一個類別並繼承android.os.AsyncTask,類別設計完成後才能使用,類別可以是內部類別(在某Activity內)或獨立的類別。通常使用AsyncTask是因為它能夠與UI元件互通,因此大都以內部類別方式設計,如下:

使用extends語法繼承AsyncTask之後的Java一般化(Generic)語法必需定義這個類別的傳入值型態、更新進度資料型態與回傳值型態,如下:

AsyncTask<傳入值型態, 更新進度型態, 結果型態>

  • 傳入值型態

代表本工作是否需要傳入資料,若需要,則要先定義資料的型態,此處只能使用參照資料型態,如IntegerStringBoolean等,若不需要任何傳入值可使用Void(大寫的V)類別。

  • 更新進度型態

在背景工作執行過程中的更新(或回報)資料的型態,例如下載工作的進度可使用Integer(35%)或Float(52.3%)這類回報資料的型態,若不需要更新資料則使用Void類別。

  • 結果(回傳)型態

背景工作完成後回傳的結果資料型態,例如下載工作完成後回傳檔名可使用String類別,或是回傳檔案的大小則使用Long類別,若不需要回傳資料則使用Void類別。

類別定義完成後,該類別內的方法中使用的傳入參數與回傳值還必須與類別義相符合,例如接下來必須實作的doInBackground方法。

2. 將工作寫在doInBackground方法中

AsyncTask是抽象類別,因此繼承它的子類別都必須實作其抽象方法,也就是唯一的doInBackground方法,字面上即是在背景工作的方法。實作方法只需要將游標停在類別定義行,按下「Alt+Enter」,如下圖:

A4254

如上圖的「Implement methods」實作方法,按下Enter後會出現方法選擇對話框,點擊實作doInBackground方法或選擇後按下Enter,如下圖:

A4255

Android Studio會自動在類別中實作方法,如下圖:

A4256-1

因為第33行定義了傳入值與回傳值都是Void,因此自動產生的doInBackground方法的規格也符合規範,開發人員可在此方法中設計耗時工作的程式碼。到目前為止,最簡單的AsyncTask設計完成了。而doInBackground方法的參數使用的是Java 1.5開始提供的陣列參數語法,在編譯時會轉換為陣列,第36行最後參數型態(與AsyncTask的傳入值型態配合)若是字串時,params[0]即代表陣列的第一個字串值,如下。

3. 產生類別並呼叫execute()

接著可依照需求,在程式碼中呼叫TestTask內部類別的建構子產生物件,再呼叫execute()方法,即可產生另一個執行緒,並在背景執行doInBackground方法內的程式碼,如下:

如果後續需要再使用這個物件,也可以將物件儲存後再呼叫execute方法,如下:

因為TestTask已定義傳入值型態為Void,因此呼叫execute方法可以不用給予參數,若是有定義傳入值型態,則exectute方法內就應該給予值入值。

提示: 呼叫execute方法後,AsyncTask會自動執行必要的方法後自動執行doInBackground方法,而不是由開發人員直接去呼叫doInBackground方法,這樣不會以背景執行緒執行。

與UI thread互通的方法

一個AsyncTask的執行流程有四個階段,四個執行的方法分別是onPreExecute、doInBackground、onProgressUpdate與onPostExecute,除了doInBackground方法之外,AsyncTask類別定義了另外三個方法能夠與UI Thread或UI元件互動,依其用途說明如下:

1. onPreExecute-之前

在背景工作執行之前會自動執行的方法,開發人員可覆寫onPreExecute,在方法內撰寫程式碼。

2. onProgressUpdate-過程

在下載過程中可以手動呼叫的方法,在doInBackground中呼叫「publishProgress方法」會自動執行onProgressUpdate方法內的程式碼。

3. onPostExecute-之後

在背景工作執行完成後會自動執行的方法,開發人員可覆寫onPostExecute,在方法內撰寫工作完成後必要的程式碼。

提示: 在類別中按下覆寫方法快速鍵「Ctrl+O」可快速選擇欲覆寫的方法,如下圖A4257

除了doInBackground,三個方法內都能與UI Thread或元件互動,例如在方法中以findViewById方法取得元件後,再設定元件屬性,如下圖與箭頭所示:

A4258

初步瞭解AsyncTask的設計後,別忘了練習,可參考接續的文章:

AsyncTask-實作練習

相關文章:

Category: Android 標籤:,

關於 Hank Tom

專長為程式語言、雲端服務開發,Linux系統管理, 任職:利拓科技 技術長,海林行動科技 技術總監 輔仁大學 兼任助理教授 ,為 Android高效入門>深度學習、CentOS 7建置、管理與伺服器架設實戰、Java網路程式設計、雲端網頁程式設計-Google App Engine應用實作 等書作者

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *