在上一節中,我們使用Handler、Thread/Runnable 、URL、HttpURLConnection等等來進行非同步下載網狀圖片。
但是採用這種方式有一些缺點,如下:
線程的開銷較大,如果每個任務都要建立一個線程,那麼程式的效率要低很多。
線程無法管理,匿名線程建立並啟動後就不受程式的控制了,如果有很多個請求發送,那麼就會啟動非常多的線程,系統將不堪重負。
另外,前面已經看到,在新線程中更新UI還必須要引入handler,這讓代碼看上去非常臃腫。
那麼有沒有比較更好好的實現方式呢?這個可以有!它就是AsyncTask
AsyncTask的特點是任務在主UI線程之外運行,而回調方法是在主UI線程中,這就有效地避免了使用Handler帶來的麻煩。
AsyncTask定義了三種泛型型別 Params,Progress和Result。
- Params 啟動任務執行的輸入參數。
- Progress 背景工作執行的百分比。
- Result 後台執行任務返回的結果。
當然,使用它還必須覆蓋它的一些抽象方法方法
doInBackground(Params...)
執行任務
onPostExecute(Result) 返回任務執行的結果,通常更新UI
onProgressUpdate (Progress... values) 進度更新
注意:紅色的是必須實現的。
第一步:設計好UI,與上節一樣
第二步:也與上節一樣。
第三步:主要是執行個體化AsyncTask,並執行execute(Params)
我們必須繼承AsyncTask,並覆蓋它的一些方法,我們這裡主要是要擷取網狀圖片,並儲存為Bitmap,以便UI根據Bitmap來更新的。
那麼需要為AsyncTask設定返回的型別參數為String,Integer,Bitmap 類定義如下:
View Code
public class MyASyncTask extends AsyncTask<String, Integer, Bitmap> {
在doInBackground(Params...) 方法中 ,接受String ....params,返回我們需要的Bitmap.當然我們這裡是擷取圖片Bitmap所以要返回Bitmap
如果你返回的需要是String或者其他複雜類型時候,需要修改類的定義參數類型為你需要返回的類型,當然接受參數也是根據你的請求需要改變。
View Code
@Override
protected Bitmap doInBackground(String... params) {
Bitmap bitmap=null;
try {
URL url = new URL(params[0]);
HttpURLConnection con=(HttpURLConnection) url.openConnection();
con.setDoInput(true);
con.connect();
InputStream inputStream=con.getInputStream();
bitmap=BitmapFactory.decodeStream(inputStream);
inputStream.close();
}
catch (MalformedURLException e) {
e.printStackTrace();
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bitmap;
}
在 onPostExecute(Result) 中是請求獲得結果後更新UI部分。你會看到他的參數就是我們類中的型別參數。代碼如下:
View Code
//執行獲得圖片資料後,更新UI:顯示圖片,隱藏進度條
@Override
protected void onPostExecute(Bitmap Result){
ImageView imgView=(ImageView)this.viewGroup.getChildAt(0);
imgView.setImageBitmap(Result);
ProgressBar bar=(ProgressBar)this.viewGroup.getChildAt(1);
bar.setVisibility(View.GONE);
}
然後怎麼用呢?在UI線程中執行吧:
MyASyncTask yncTask=new MyASyncTask(this,frameLayout);
yncTask.execute(params);
運行結果與上節大同小異