android: 使用 AsyncTask

9.2.4    使用 AsyncTask異步

 

不過爲了更加方便咱們在子線程中對 UI 進行操做,Android 還提供了另一些好用的工 具,AsyncTask 就是其中之一。藉助 AsyncTask,即便你對異步消息處理機制徹底不瞭解, 也能夠十分簡單地從子線程切換到主線程。固然,AsyncTask 背後的實現原理也是基於異步 消息處理機制的,只是 Android 幫咱們作了很好的封裝而已。ide

首先來看一下 AsyncTask 的基本用法,因爲 AsyncTask 是一個抽象類,因此若是咱們想 使用它,就必需要建立一個子類去繼承它。在繼承時咱們能夠爲 AsyncTask 類指定三個泛型 參數,這三個參數的用途以下。線程

1.    Params繼承

在執行 AsyncTask 時須要傳入的參數,可用於在後臺任務中使用。io

2.    Progressast

後臺任務執行時,若是須要在界面上顯示當前的進度,則使用這裏指定的泛型做爲 進度單位。class

3.    Result後臺

當任務執行完畢後,若是須要對結果進行返回,則使用這裏指定的泛型做爲返回值 類型。泛型

所以,一個最簡單的自定義 AsyncTask 就能夠寫成以下方式:變量

 

class DownloadTask extends AsyncTask<Void, Integer, Boolean> {

……

}

這裏咱們把 AsyncTask 的第一個泛型參數指定爲 Void,表示在執行 AsyncTask 的時候不 須要傳入參數給後臺任務。第二個泛型參數指定爲 Integer,表示使用整型數據來做爲進度顯 示單位。第三個泛型參數指定爲 Boolean,則表示使用布爾型數據來反饋執行結果。

固然,目前咱們自定義的 DownloadTask 仍是一個空任務,並不能進行任何實際的操做, 咱們還須要去重寫 AsyncTask 中的幾個方法才能完成對任務的定製。常常須要去重寫的方法 有如下四個。

1.    onPreExecute()

這個方法會在後臺任務開始執行以前調用,用於進行一些界面上的初始化操做,比 如顯示一個進度條對話框等。

2.    doInBackground(Params...)

這個方法中的全部代碼都會在子線程中運行,咱們應該在這裏去處理全部的耗時任 務。任務一旦完成就能夠經過 return 語句來將任務的執行結果返回,若是 AsyncTask 的 第三個泛型參數指定的是 Void,就能夠不返回任務執行結果。注意,在這個方法中是不 能夠進行 UI 操做的,若是須要更新 UI 元素,好比說反饋當前任務的執行進度,能夠調 用 publishProgress(Progress...)方法來完成。

3.    onProgressUpdate(Progress...)

當在後臺任務中調用了 publishProgress(Progress...)方法後,這個方法就會很快被調 用,方法中攜帶的參數就是在後臺任務中傳遞過來的。在這個方法中能夠對 UI 進行操 做,利用參數中的數值就能夠對界面元素進行相應地更新。

4.    onPostExecute(Result)

當後臺任務執行完畢並經過 return 語句進行返回時,這個方法就很快會被調用。返 回的數據會做爲參數傳遞到此方法中,能夠利用返回的數據來進行一些 UI 操做,好比 說提醒任務執行的結果,以及關閉掉進度條對話框等。

所以,一個比較完整的自定義 AsyncTask 就能夠寫成以下方式:

 

class DownloadTask extends AsyncTask<Void, Integer, Boolean> {

 

 @Override

protected void onPreExecute() {

progressDialog.show(); // 顯示進度對話框

}

 

@Override

protected Boolean doInBackground(Void... params) {

try {

while (true) {

int downloadPercent = doDownload(); // 這是一個虛構的方法

publishProgress(downloadPercent);

if (downloadPercent >= 100) {

break;

}

}

} catch (Exception e) {

return false;

}

return true;

}

 

@Override

protected void onProgressUpdate(Integer... values) {

// 在這裏更新下載進度

progressDialog.setMessage("Downloaded " + values[0] + "%");

}

 

 

@Override

protected void onPostExecute(Boolean result) {

progressDialog.dismiss(); // 關閉進度對話框

// 在這裏提示下載結果

if (result) {

Toast.makeText(context, "Download succeeded", Toast.LENGTH_SHORT).show();

} else {

Toast.makeText(context, " Download failed", Toast.LENGTH_SHORT).show();

}

}

}

 

在這個 DownloadTask 中,咱們在 doInBackground()方法裏去執行具體的下載任務。這個方法裏的代碼都是在子線程中運行的,於是不會影響到主線程的運行。注意這裏虛構了一個 doDownload()方法,這個方法用於計算當前的下載進度並返回,咱們假設這個方法已經存在 了 。 在 得 到 了 當 前 的 下 載 進 度 後 , 下 面 就 該 考 慮 如 何 把 它 顯 示 到 界 面 上 了 , 由 於 doInBackground()方法是在子線程中運行的,在這裏確定不能進行 UI 操做,因此咱們能夠調 用 publishProgress()方法並將當前的下載進度傳進來,這樣 onProgressUpdate()方法就會很快 被調用,在這裏就能夠進行 UI 操做了。

當下載完成後,doInBackground()方法會返回一個布爾型變量,這樣 onPostExecute()方 法就會很快被調用,這個方法也是在主線程中運行的。而後在這裏咱們會根據下載的結果來 彈出相應的 Toast 提示,從而完成整個 DownloadTask 任務。

簡單來講,使用 AsyncTask 的訣竅就是,在 doInBackground()方法中去執行具體的耗時 任務,在 onProgressUpdate()方法中進行 UI 操做,在 onPostExecute()方法中執行一些任務的 收尾工做。

若是想要啓動這個任務,只需編寫如下代碼便可:

new DownloadTask().execute();

以上就是 AsyncTask 的基本用法,怎麼樣,是否是感受簡單方便了許多?咱們並不須要 去考慮什麼異步消息處理機制,也不須要專門使用一個 Handler 來發送和接收消息,只須要 調用一下 publishProgress()方法就能夠輕鬆地從子線程切換到 UI 線程了。

相關文章
相關標籤/搜索