為什么要異步任務(wù)
- android單線程模型。
- 耗時操作放在非主線程中執(zhí)行。
AsyncTask為何而生
- 子線程中更新UI。
- 封裝,簡化異步操作。
構(gòu)建AsyncTask子類的參數(shù)
- AsyncTask<Params,Progress,Result>是一個抽象類,通常用于別繼承。
Params:啟動任務(wù)是輸入的參數(shù)類型。
Progress:后臺任務(wù)執(zhí)行中返回進度值的類型。
Result:后臺執(zhí)行任務(wù)完成后返回結(jié)果的類型。
構(gòu)建AsyncTask子類的回調(diào)方法
- doInBackground:必須重寫,異步執(zhí)行后臺線程將要完成的任務(wù)。
- onPreExecute:執(zhí)行后臺耗時操作前被調(diào)用,通常用戶完成一些初始化操作。
- onPostExecute:當(dāng)doInBackground完成后,系統(tǒng)會自動調(diào)用onPostExecute方法,并將doInBackground方法返回的值傳給該方法。
- onProgressUpdate:在doInBackground方法中調(diào)用publishProgress方法更新任務(wù)的執(zhí)行進度后,就會觸發(fā)該方法。
獲取網(wǎng)絡(luò)圖片的例子
- 從網(wǎng)絡(luò)中獲取一張圖片是一個耗時操作,可放在AsyncTask的doInBackground()方法中執(zhí)行,在獲取圖片前調(diào)用 onPreExecute方法,設(shè)置一個ProgressBar給用戶看,當(dāng)耗時操作完成時,把獲取到的圖片 在onPostExecute方法展現(xiàn)出來。
/**
* Created by X on 2016/5/12 0012.
* 開啟異步線程去做耗時操作
*/
class MyAsyncTask extends AsyncTask<String,Void,Bitmap> {
@Override
protected void onPreExecute() {
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
progressBar.setVisibility(View.GONE);
image.setImageBitmap(bitmap);
}
@Override
protected Bitmap doInBackground(String... params) {
//獲取傳遞進來的參數(shù)
String url=params[0];
Bitmap bitmap=null;
URLConnection connection;
InputStream is;
try {
//獲取網(wǎng)絡(luò)連接的對象
connection=new URL(url).openConnection();
is=connection.getInputStream();
BufferedInputStream bis=new BufferedInputStream(is);
Thread.sleep(1000);
//通過decodeStream解析輸入流
bitmap= BitmapFactory.decodeStream(bis);
is.close();
bis.close();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return bitmap;
}
}
-
最后在onCreate方法中調(diào)用AsyncTask的execute方法。
myAsyncTask=new MyAsyncTask(); //設(shè)置傳遞進去的參數(shù) myAsyncTask.execute(URL);
模擬進度條例子
-
在doInBackground方法中進行進度值的賦值,把值賦給publishProgress方法。
@Override protected Void doInBackground(Void... params) { //模擬進度更新 for (int i=0;i<100;i++){ if (isCancelled()){ break; } publishProgress(i); try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } } return null; } -
在onProgressUpdate方法中進行進度值的更新。
@Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); if (isCancelled()){ return; } //獲取進度更新值 mProgressBar.setProgress(values[0]); } -
但我們結(jié)束當(dāng)前activity或者fragment是就需要結(jié)束當(dāng)前的AsyncTask,可以和activity是onPause方法綁定,把異步標(biāo)記為cancel,再在doInBackground和onProgressUpdate方法中進行判斷,如果標(biāo)記為cancel就不執(zhí)行操作。
@Override protected void onPause() { super.onPause(); if (mAsyncTask!=null && mAsyncTask.getStatus()==AsyncTask.Status.RUNNING){ //cancel方法只是將對應(yīng)的AsyncTask標(biāo)記為cancel,而不是正在取消一個線程 mAsyncTask.cancel(true); } }
AsyncTask注意事項
- 必須在UI線程中創(chuàng)建AsyncTask實例。
- 必須在UI線程中調(diào)用AsyncTask的execute()方法。
- 重寫的四個方法是系統(tǒng)自動調(diào)用的,不應(yīng)手動調(diào)用。
- 每個AsyncTask只能被執(zhí)行一次,多次調(diào)用會引發(fā)異常。