使用异步任务加载网络上的图片
我们知道,如果要加载一个很耗时的操作,会阻塞主线程,这时我们可以想到开启一个新的线程,避免阻塞,在android中也有这样的问题,我们可以用异步任务来操作,异步任务也是开启一个线程,线程里面发一个消息,然后通知去改变UI。
废话不多说,我们先看一个例子:我们可以打开这个网址:http://img1.3lian.com/img2011/07/20/05.jpg可以看到一副很好看的图片,我们就要把这个图片显示出来,首先,还是先要布局,我们要显示一幅图片,所以我们的布局中需要一个ImageView,布局很简单,一个ImageView就可以了:
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 android:layout_width="match_parent"
5 android:layout_height="match_parent">
6 <ImageView
7 android:id="@+id/img"
8 android:scaleType="fitXY"
9 android:layout_width="match_parent"
10 android:layout_height="match_parent"/>
11 </LinearLayout>
之后我们要写一个Activity显示这个图片,不过要加载网络上的图片,我们需要从一个URL的流中获取这个图片,所以我们要写一个方法来获取这张图片:
1 public Drawable loadImages(String url) {
2 try {
3 return Drawable.createFromStream((InputStream)(new URL(url)).openStream(), "test");
4 }
5 catch (IOException e) {
6 e.printStackTrace();
7 }
8 return null;
9 }
从URL中打开流,强制转换成InputStream,然后从流中拿到Drawable。
既然可以获取图片了,我们要考虑一个问题,如果图片很大,加载的很慢怎么办,我们岂不是要等很久?不要紧,这时候我们就可以用异步任务了。
首先我们要写一个内部类,这个类部类是继承自异步任务的,需要重载里面的doBackGround方法:
1 private class ImageAsynTask extends AsyncTask<Void, Void, Drawable> {
2
3 @Override
4 protected Drawable doInBackground (Void... params) {
5 String url = "http://img1.3lian.com/img2011/07/20/05.jpg";
6 return loadImages(url);
7 }
8
9 @Override
10 protected void onPostExecute (Drawable result) {
11 super.onPostExecute(result);
12 mDialog.dismiss();
13 mImage.setImageDrawable(result);
14 }
15
16 @Override
17 protected void onPreExecute () {
18 super.onPreExecute();
19 mDialog.show();
20 }
21 }
首先看这个方法:onPreExecute()这个方法是在doInBackGround前面执行。我们把这个方法写出来,我们需要在获取图片之前等待的时间里,写一个progressDialog,显示出来,提示用户,目前正在加载图片,需要等待一段时间。同时在后台操作doBackGround运行。
在doBackGround完成之后就会执行onPostExecute(Drawable result)方法,看这个方法就知道,必须在doBackGround完成之后,把得到的结果Drawable作为参数传到onPostExecute方法里面去,执行这个方法就表示已经加载完了,我们需要将progressDialog消失掉,然后把图片显示出来就可以了,整个过程很简单。
看下整个Activity的代码:
1 package com.test.asyntask;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.net.URL;
6
7 import android.app.Activity;
8 import android.app.ProgressDialog;
9 import android.graphics.drawable.Drawable;
10 import android.os.AsyncTask;
11 import android.os.Bundle;
12 import android.widget.ImageView;
13
14 import com.test.R;
15
16 public class AsynTask extends Activity {
17
18 private ImageView mImage;
19 private ProgressDialog mDialog;
20
21 @Override
22 protected void onCreate (Bundle savedInstanceState) {
23 super.onCreate(savedInstanceState);
24 setContentView(R.layout.asyn_task);
25
26 mDialog = new ProgressDialog(this);
27 mDialog.setTitle("请稍等");
28 mDialog.setMessage("正在加载...");
29
30 mImage = (ImageView) findViewById(R.id.img);
31 new ImageAsynTask().execute();
32 }
33
34 private class ImageAsynTask extends AsyncTask<Void, Void, Drawable> {
35
36 @Override
37 protected Drawable doInBackground (Void... params) {
38 String url = "http://img1.3lian.com/img2011/07/20/05.jpg";
39 return loadImages(url);
40 }
41
42 @Override
43 protected void onPostExecute (Drawable result) {
44 super.onPostExecute(result);
45 mDialog.dismiss();
46 mImage.setImageDrawable(result);
47 }
48
49 @Override
50 protected void onPreExecute () {
51 super.onPreExecute();
52 mDialog.show();
53 }
54 }
55
56 @Override
57 protected void onDestroy () {
58 super.onDestroy();
59 mDialog.dismiss();
60 }
61
62 public Drawable loadImages(String url) {
63 try {
64 return Drawable.createFromStream((InputStream)(new URL(url)).openStream(), "test");
65 }
66 catch (IOException e) {
67 e.printStackTrace();
68 }
69 return null;
70 }
71 }
运行一下,看下效果:
1.显示progressDialog的时候,在加载图片但是图片还没有加载出来的时候:
2.看一下显示出来的图片吧:
可以看到,加载完成后,图片可以显示出来了。
另外需要注意的是,需要在manifest里面加入链接网络的权限:
1 <uses-permission android:name="android.permission.INTERNET"/>
另外在onDestory()的时候要把progressDialog dismiss掉,不让在退出应用程序的时候会报错。
好了就到这儿吧,外面打很大的雷,估计下雨了吧,我还没带伞呢,哎,又得淋雨回去了啊。。。。悲惨啊。。。
哦,对了,把源代码传上来吧,里面的内容很多,都是写的例子程序,在com.test.asyntask包里面。