在 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 可以完成的一个很好的例子。
然而,该示例目前存在问题
- 可能的内存泄漏
- 如果在异步任务完成之前不久有屏幕旋转,应用程序崩溃。
详情见: