使用异步任务加载网络上的图片
我们知道,如果要加载一个很耗时的操作,会阻塞主线程,这时我们可以想到开启一个新的线程,避免阻塞,在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包里面。