轉自:http://406547509.blog.163.com/blog/static/456753862010112914328899/
是我們在開發Android程式時遇到較耗時任務的處理,如I/O訪問的資料庫操作、網路訪問等情況時造成UI假死等問題,通過 AsyncTask可以很好的解決這個問題,就今天以在Android中執行Downloader.downloadFile(url),可能會堵塞整個介面。顯然這會影響使用者體驗,我們如何解決這個問題呢?
方法一、
建立一個新的線程執行我們的任務,使用Thread類,在 run(){}中寫入任務代碼,比如:
new Thread(new Runnable() {
public void run() {
Downloader.downloadFile(url);
}
}).start();
但使用Thread會產生一些意想不到的問題,需要程式員用更多的代碼手動的維護它。
方法二: Android SDK為我們提供了一個背景工作的處理工具AsyncTask。AsyncTask就是一個封裝過的背景工作類顧名思義就是非同步任務,方便我們維護,Android開發網提示這樣的好處可以解決一些安全執行緒問題,AsyncTask直接繼承於Object類,位置為 android.os.AsyncTask。要使用AsyncTask工作我們要提供三個泛型參數,並重載四個方法(至少重載一個)。
三個泛型:
Param ,任務執行器需要的資料類型
Progress 後台計算中使用的進度單位元據類型
Result 後台計算返回結果的資料類型
有些參數是可以設定為不使用的,只要傳遞為Void型即可,比如AsyncTask
四個步驟:
onPreExecute(),執行預先處理,它運行於UI線程,可以為背景工作做一些準備工作,比如繪製一個進度條控制項。
doInBackground(Params...),後台進程執行的具體計算在這裡實現,doInBackground(Params...)是AsyncTask的關鍵,此方法必須重載。在這個方法內可以使用 publishProgress(Progress...)改變當前的進度值。
onProgressUpdate(Progress...),運行於UI線程。如果在doInBackground(Params...) 中使用了publishProgress(Progress...),就會觸發這個方法。在這裡可以對進度條控制項根據進度值做出具體的響應。
onPostExecute(Result),運行於UI線程,可以對背景工作的結果做出處理,結果就是doInBackground(Params...)的傳回值。此方法也要經常重載,如果Result為null表明背景工作沒有完成(被取消或者出現異常)。
Java代碼
public class main extends Activity {
ImageView imageView01;
TextView textView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textView = (TextView) this.findViewById(R.id.TextView01);
imageView01 = (ImageView) this.findViewById(R.id.ImageView01);
GetImage getImage = new GetImage();
getImage.execute("http://hi.csdn.net/attachment/201010/27/0_1288149117Yk8W.gif");
}
private class GetImage extends AsyncTask {
public GetImage() {
super();
// TODO Auto-generated constructor stub
}
@Override
protected void onCancelled() {
Log.i("czb", "onCancelled is running...");
super.onCancelled();
}
@Override
protected void onPostExecute(Object result) {
/*
* 此方法在主線程執行,任務執行的結果作為此方法的參數返回
*/
Log.i("czb", "onPostExecute is running...");
Log.i("czb", "result == null ? " + (result == null));
imageView01.setImageBitmap((Bitmap)result);
super.onPostExecute(result);
}
@Override
protected void onPreExecute() {
/*
* 執行預先處理,它運行於UI線程,可以為背景工作做一些準備工作,比如繪製一個進度條控制項
*/
Log.i("czb", "onPreExecute is running...");
super.onPreExecute();
}
@Override
protected void onProgressUpdate(Object... values) {
/*
* 此方法在主線程執行,用於顯示任務執行的進度。
*/
Log.i("czb", "onProgressUpdate is running...");
// 由publishProgress傳遞的值
Log.i("czb", "values " + values[0]);
super.onProgressUpdate(values);
}
@Override
protected Object doInBackground(Object... params) {
/*
* 此方法在後台線程執行,完成任務的主要工作,通常需要較長的時間。
* 在執行過程中可以調用publicProgress(Progress…)來更新任務的進度。
*/
Log.i("czb", "doInBackground is running...");
try {
Bitmap bitmap;
HttpClient client = new DefaultHttpClient();
// params[0]代表串連的url
URI uri = URI.create((String) params[0]);
HttpGet get = new HttpGet(uri);
HttpResponse response = client.execute(get);
HttpEntity entity = response.getEntity();
long length = entity.getContentLength();
Log.i("czb", " " + length);
InputStream in = entity.getContent();
if (in != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
/*byte[] buf = new byte[128];
int ch = -1;
int count = 0;
while ((ch = in.read(buf)) != -1) {
baos.write(buf, 0, ch);
count += ch;
if (length > 0) {
// 如果知道響應的長度,調用publishProgress()更新進度
// onProgressUpdate讀取進度
publishProgress((int) ((count / (float) length) * 100));
}
// 為了在模擬器中清楚地看到進度,讓線程休眠100ms
//Thread.sleep(100);
}*/
bitmap = BitmapFactory.decodeStream(in);
in.close();
baos.close();
return bitmap;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
}