android 多线程异步下载图片,Android多线程分析之五:使用AsyncTask异步下载图像

本文详细介绍了Android中如何使用AsyncTask进行异步图片下载,展示了从创建任务、设置UI更新到任务完成的完整流程。重点在于'三参数四步骤'的运用和AysncTask的使用限制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android多线程分析之五:使用AsyncTask异步下载图像在本系列文章的第一篇《Android多线程分析之一:使用Thread异步下载图像》中,曾演示了如何使用 Thread 来完成异步任务。Android 为了简化在 UI 线程中完成异步任务(毕竟 UI 线程是 app 最重要的线程),实现了一个名为 AysncTask 的模板类。使用 AysncTask 能够在异步任务进行的同时,将任务进度状态反馈给 UI 线程(如让 UI 线程更新进度条)。正是由于它与 UI 线程紧密相关,使用的时候要就有一些限制,AysncTask 必须在 UI 线程中创建,并在 UI 线程中启动(通过调用其 execute() 方法);此外,AysncTask 设计的目的是用于一些耗时较短的任务,如果是耗时较长的任务不推荐使用 AysncTask。

可以用简化记忆 “三参数,四步骤” 来学习 AysncTask。 即带有三个模板参数 ,四个处理步骤:onPreExecute,doInBackground,onProgressUpdate,onPostExecute。

三参数:

Params 是异步任务所需的参数类型,也即 doInBackground(Params... params) 方法的参数类型;Progress 是指进度的参数类型,也即 onProgressUpdate(Progress... values) 方法的参数类型;

Result 是指任务完成返回的参数类型,也即 onPostExecute(Result result) 或 onCancelled(Result result) 方法的参数类型。

如果某一个参数类型没有意义或没有被用到,传递 void 即可。

四步骤:

protected void onPreExecute():在 UI 线程中运行,在异步任务开始之前被执行,以便 UI 线程完成一些初始化动作,如将进度条清零;

protected abstract Result doInBackground(Params... params):在后台线程中运行,这是完成异步任务的地方,它是抽象接口,子类必须提供实现;

protected void onProgressUpdate(Progress... values):在 UI 线程中运行,在异步任务执行的过程中可以通过调用 void publishProgress(Progress... values) 方法通知 UI 线程在 onProgressUpdate 方法内更新进度状态;

protected void onPostExecute(Result result):在 UI 线程中运行,当异步任务完成之后被执行,以便 UI 线程更新任务完成状态。

AysncTask 支持取消异步任务,当异步任务被取消之后,上面的步骤四就不会被执行了,取而代之将执行 onCancelled(Result result),以便 UI 线程更新任务被取消之后的状态。谨记:上面提到的这些方法都是回调函数,不需要用户手动去调用。

以前的 AysncTask 是基于单一后台线程实现的,而从 Android 3.0 起 AysncTask 是基于 Android 的并发库(java.util.concurrent)实现的,本文中不会展开讨论其具体实现,只是演示如何使用 AysncTask。

使用示例:

有了前面的轮廓介绍,再来使用 AysncTask 是非常容易的,下面的例子与 《使用Thread异步下载图像》中的例子非常相似,只不过是使用 AysncTask 来完成异步任务罢了。

这是一个使用 AysncTask 从网络上异步下载图片并在 ImageView 中显示的的简单示例。因为需要访问网络,所以要在 manifest.xml 中添加网络访问权限:

布局文件很简单,一个 Button,一个 ImageView:

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

android:padding="10dip" >

android:id="@+id/LoadButton"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="Load">

android:id="@+id/ImageVivew"

android:layout_width="match_parent"

android:layout_height="400dip"

android:scaleType="centerInside"

android:padding="2dp">

接下来看代码:

首先来看定义:图片的 url 路径,两个消息值以及一些控件:

private static final String sImageUrl = "http://fashion.qqread.com/ArtImage/20110225/0083_13.jpg";

private Button mLoadButton;

private ImageView mImageView;然后来看控件的设置:

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Log.i("UI thread", " >> onCreate()");

mImageView = (ImageView)this.findViewById(R.id.ImageVivew);

mLoadButton = (Button)this.findViewById(R.id.LoadButton);

mLoadButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

LoadImageTask task = new LoadImageTask(v.getContext());

task.execute(sImageUrl);

}

});

}LoadImageTask 继承自 AysncTask,由这个类去完成异步图片下载任务,并相应地更新 UI 状态。

class LoadImageTask extends AsyncTask

{

private ProgressDialog mProgressBar;

LoadImageTask(Context context)

{

mProgressBar = new ProgressDialog(context);

mProgressBar.setCancelable(true);

mProgressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

mProgressBar.setMax(100);

}

@Override

protected Bitmap doInBackground(String

918e8df969f9f8c8d002f25cda86cade.png params) {

Log.i("Load thread", " >> doInBackground()");

Bitmap bitmap = null;

try{

publishProgress(10);

Thread.sleep(1000);

InputStream in = new java.net.URL(sImageUrl).openStream();

publishProgress(60);

Thread.sleep(1000);

bitmap = BitmapFactory.decodeStream(in);

in.close();

} catch (Exception e) {

e.printStackTrace();

}

publishProgress(100);

return bitmap;

}

@Override

protected void onCancelled() {

super.onCancelled();

}

@Override

protected void onPreExecute() {

mProgressBar.setProgress(0);

mProgressBar.setMessage("Image downloading

918e8df969f9f8c8d002f25cda86cade.png %0");

mProgressBar.show();

Log.i("UI thread", " >> onPreExecute()");

}

@Override

protected void onPostExecute(Bitmap result) {

Log.i("UI thread", " >> onPostExecute()");

if (result != null) {

mProgressBar.setMessage("Image downloading success!");

mImageView.setImageBitmap(result);

}

else {

mProgressBar.setMessage("Image downloading failure!");

}

mProgressBar.dismiss();

}

@Override

protected void onProgressUpdate(Integer

918e8df969f9f8c8d002f25cda86cade.png values) {

Log.i("UI thread", " >> onProgressUpdate() %" + values[0]);

mProgressBar.setMessage("Image downloading

918e8df969f9f8c8d002f25cda86cade.png %" + values[0]);

mProgressBar.setProgress(values[0]);

}

};

在 LoadImageTask 中,前面提到的四个步骤都涉及到了:

首先在任务开始之前在 onPreExecute() 方法中设置进度条的初始状态(UI线程);然后在下载线程中执行 doInBackground() 以完成下载任务,并在其中调用 publishProgress() 来通知 UI 线程更新进度状态;UI 线程在 onProgressUpdate() 中得知进度,并更新进度条(UI线程);最后下载任务完成,UI 线程在 onPostExecute() 中得知下载好的图像,并更新UI显示该图像(UI线程)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值