Android 提供了一套專門用於異步處理的類。即:AsyncTask 類。使用這個類可以爲耗時程序開闢一個新線程進行處理,處理完時返回。
AsyncTask<Params, Progress, Result> 是一個抽象類,通常用於被集成。集成 AsyncTask 時需要制定如下三個泛型參數(傳遞的數據都是對應類型的數組,數組都是可變長的):
Params:啓動任務執行的輸入參數的類型。對應 execute() 向 doInBackground() 的傳遞類型。
Progress:後臺任務完成的進度值的類型。對應 publishProgress() 向 progressUpdate() 傳遞的類型。
Result:後臺執行任務完成後返回結果的類型。對應doInBackground()的返回類型和傳遞給 onPostExecute() 的類型
AsyncTask 類主要用到的幾個內部回調函數有以下四個,可以根據需要重寫,其中 doInBackGround(Params...) 必須重寫:
onPreExecute():該方法將在執行實際的後臺操作前被UI thread調用。可以在該方法中做一些準備工作,如在界面上顯示一個進度條。
doInBackGround(Params... params):將在onPreExecute 方法執行後馬上執行,該方法運行在後臺線程中。這裏將主要負責執行那些很耗時的後臺計算工作。可以調用
publishProgress(Progress... values) 方法來更新實時的任務進度。該方法是抽象方法,子類必須實現。
onProgressUpdate(Progress... values):在publishProgress方法被調用後,UI thread將調用這個方法從而在界面上展示任務的進展情況,例如通過一個進度條進行展示。
回調邏輯關係如下:
回調邏輯關係說明:
1.主線程調用AsynTask子類實例的 execute(Params... params 方法後,首先會調用 onPreExecute() 方法。onPreExecute() 在主線程中運行,可以用來寫一些開始提示代碼或者進度條等。
2.之後啓動新線程,調用 doInBackground(Params... params ) 方法,進行異步數據處理。
3.處理完畢之後異步線程結束,在主線程中調用 onPostExecute(Result result) 方法。onPostExecute(Result result) 可以進行一些結束提示處理。
使用 AsyncTask 只需要如下三步即可:
1.創建 AsyncTask 的子類,併爲三個泛型參數指定類型。如果某個泛型參數不需要指定類型,則可將它指定爲Void。
2.根據需要,實現 AsyncTask 的方法。
3.調用 AsyncTask 子類的實例的 execute(Params...)開始執行 AsyncTask 任務。
爲了正確的使用AsyncTask類,必須遵守以下是幾條準則:
1.必須在UI thread 中創建 AsyncTask 的實例。
2.必須在UI thread 中調用 AsyncTask 的實例的 execute() 方法。
3. AsyncTask 的 onPreExecute()、onPostExecute(Result result)、doInBackground(Params... params)、onProgressUpdate(Progress... values)這幾個方法不該由程序員來調用,而是由 Android 系統負責調用。
4.每個 AsyncTask 只能被執行一次,多次調用時將會出現異常
例1:使用異步任務下載
public class AsyncTaskTest extends Activity
{
private TextView show;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
show = (TextView) findViewById(R.id.show);
}
// 重寫該方法,爲界面的按鈕提供事件響應方法
public void download(View source) throws MalformedURLException
{
DownTask task = new DownTask(this);
task.execute(new URL("http://www.crazyit.org/ethos.php"));
}
class DownTask extends AsyncTask<URL, Integer, String>
{
// 可變長的輸入參數,與AsyncTask.exucute()對應
ProgressDialog pdialog;
// 定義記錄已經讀取行的數量
int hasRead = 0;
Context mContext;
public DownTask(Context ctx)
{
mContext = ctx;
}
@Override
protected String doInBackground(URL... params)
{
StringBuilder sb = new StringBuilder();
try
{
URLConnection conn = params[0].openConnection();
// 打開conn連接對應的輸入流,並將它包裝成BufferedReader
BufferedReader br = new BufferedReader(
new InputStreamReader(conn.getInputStream()
, "utf-8"));
String line = null;
while ((line = br.readLine()) != null)
{
sb.append(line + "\n");
hasRead++;
publishProgress(hasRead);
}
return sb.toString();
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String result)
{
// 返回HTML頁面的內容
show.setText(result);
pdialog.dismiss();
}
@Override
protected void onPreExecute()
{
pdialog = new ProgressDialog(mContext);
// 設置對話框的標題
pdialog.setTitle("任務正在執行中");
// 設置對話框 顯示的內容
pdialog.setMessage("任務正在執行中,敬請等待...");
// 設置對話框不能用“取消”按鈕關閉
pdialog.setCancelable(false);
// 設置該進度條的最大進度值
pdialog.setMax(202);
// 設置對話框的進度條風格
pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
// 設置對話框的進度條是否顯示進度
pdialog.setIndeterminate(false);
pdialog.show();
}
@Override
protected void onProgressUpdate(Integer... values)
{
// 更新進度
show.setText("已經讀取了【" + values[0] + "】行!");
pdialog.setProgress(values[0]);
}
}
}