在 Android 中使用 AsyncTask 下載影象
本教程介紹如何使用 Android 中的 AsyncTask 下載 Image。下面的示例在下載過程中顯示進度條的同時下載影象。
瞭解 Android AsyncTask
非同步任務使你可以實現 MultiThreading 而不會弄髒執行緒。AsyncTask 可以正確,方便地使用 UI 執行緒。它允許執行後臺操作並在 UI 執行緒上傳遞結果。如果你正在執行與 UI 相關的隔離操作,例如下載資料以顯示在列表中,請繼續使用 AsyncTask。
- 理想情況下,AsyncTasks 應該用於短操作(最多幾秒鐘)。
- 非同步任務由 3 種泛型型別定義,稱為 Params,Progress 和 Result,以及 4 個步驟,稱為
onPreExecute()
,doInBackground()
,onProgressUpdate()
和onPostExecute()
。 - 在
onPreExecute()
中,你可以定義程式碼,這些程式碼需要在後臺處理開始之前執行。 - doInBackground 有需要在後臺執行的程式碼,這裡在
doInBackground()
中我們可以通過publishProgress()
方法多次向結果執行緒傳送結果,通知後臺處理已經完成,我們可以簡單地返回結果。 onProgressUpdate()
方法從doInBackground()
方法接收進度更新,通過publishProgress()
方法釋出,此方法可以使用此進度更新來更新事件執行緒onPostExecute()
方法處理doInBackground()
方法返回的結果。- 使用的泛型型別是
- 引數,執行時傳送給任務的引數型別
- 進度,後臺計算期間釋出的進度單元的型別。
- 結果,後臺計算結果的型別。
- 如果非同步任務不使用任何型別,則可以將其標記為 Void 型別。
- 可以通過呼叫
cancel(boolean)
方法取消正在執行的非同步任務。
使用 Android AsyncTask 下載影象
你的 .xml 版面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/downloadButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Click Here to Download" />
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="Your image will appear here" />
</LinearLayout>
.java 類
package com.javatechig.droid;
import java.io.InputStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
public class ImageDownladerActivity extends Activity {
private ImageView downloadedImg;
private ProgressDialog simpleWaitDialog;
private String downloadUrl = "http://www.9ori.com/store/media/images/8ab579a656.jpg";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.asynch);
Button imageDownloaderBtn = (Button) findViewById(R.id.downloadButton);
downloadedImg = (ImageView) findViewById(R.id.imageView);
imageDownloaderBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
new ImageDownloader().execute(downloadUrl);
}
});
}
private class ImageDownloader extends AsyncTask {
@Override
protected Bitmap doInBackground(String... param) {
// TODO Auto-generated method stub
return downloadBitmap(param[0]);
}
@Override
protected void onPreExecute() {
Log.i("Async-Example", "onPreExecute Called");
simpleWaitDialog = ProgressDialog.show(ImageDownladerActivity.this,
"Wait", "Downloading Image");
}
@Override
protected void onPostExecute(Bitmap result) {
Log.i("Async-Example", "onPostExecute Called");
downloadedImg.setImageBitmap(result);
simpleWaitDialog.dismiss();
}
private Bitmap downloadBitmap(String url) {
// initilize the default HTTP client object
final DefaultHttpClient client = new DefaultHttpClient();
//forming a HttpGet request
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
//check 200 OK for success
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ImageDownloader", "Error " + statusCode +
" while retrieving bitmap from " + url);
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
// getting contents from the stream
inputStream = entity.getContent();
// decoding stream data back into image Bitmap that android understands
final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
} catch (Exception e) {
// You Could provide a more explicit error message for IOException
getRequest.abort();
Log.e("ImageDownloader", "Something went wrong while" +
" retrieving bitmap from " + url + e.toString());
}
return null;
}
}
}
由於目前沒有例子的評論欄位(或者我沒有找到它或我沒有獲得它的許可),這裡有一些評論:
這是使用 AsyncTask 可以完成的一個很好的例子。
然而,該示例目前存在問題
- 可能的記憶體洩漏
- 如果在非同步任務完成之前不久有螢幕旋轉,應用程式崩潰。
詳情見: