handler加线程模式实现android应用的异步加载

android开发经常需要访问加载网络图片,今天我做了一个笔记,一步一步由浅入深,来用handler+线程的模式来加载网络的图片,下面看看第一种情况:"每次创建一个线程来的模式"

首先创建一个handler用来接收消息,为指定的imageView设置图片:

Handler handler = new Handler(){public void handleMessage(Message msg) {ImageView iv = (ImageView) findViewById(msg.arg1);iv.setImageDrawable((Drawable) msg.obj);};}; 下面这个方法是加载指定url的图片,并且发送消息给handler

private void loadImage(final String string, final int id) {// TODO Auto-generated method stubnew Thread(){public void run() {try {Drawable drawable = Drawable.createFromStream(new URL(string).openStream(),"image.png");SystemClock.sleep(2000); //模拟访问网络Message msg = handler.obtainMessage();msg.arg1 = id; //将imageView的id传送msg.obj = drawable; //加载出的drawable实体对象handler.sendMessage(msg);} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}};}.start();} 在onCreate方法中,这样调用,为imageView来加载图片:

loadImage(":8080/Struts2JQueryJson/test/one.png",R.id.imageOne);loadImage(":8080/Struts2JQueryJson/test/two.jpg",R.id.imageTwo);loadImage(":8080/Struts2JQueryJson/test/three.jpg",R.id.imageThree);loadImage(":8080/Struts2JQueryJson/test/four.png",R.id.imageFour);

可以看到,我们每次调用一次loadImage方法都会新开启一个线程,这样做有一点坏处,就是当我们有很多图片需要加载的时候,是需要开启大量的线程来访问网络的,这样性能开销很大,所以我们接下来看看,利用线程池+handler的模式来访问网络图片,这样可以改善不断的开线程造成的性能开销很大的问题。

线程池+handler

这次,我们的loadImage方法会创建一个拥有四个线程的线程池,来加载网络图片:

//新建一个拥有4个线程的线程池ExecutorService service = Executors.newFixedThreadPool(4);private void loadImage(final String string,final int id) {// TODO Auto-generated method stub// serivce.submit(new Runnable() { }) 来确保下载是在线程池的线程中。service.submit(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubtry {final Drawable drawable = Drawable.createFromStream(new URL(string).openStream(),"haha.png");//SystemClock.sleep(3000);//模拟网络访问网络的时间handler.post(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubImageView iv = (ImageView) findViewById(id);iv.setImageDrawable(drawable);}});} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}); onCreate中的代码是不变的

//加载四张网络图片,将图片的url和索要显示图片的iamgeviewd的的id当做参数传入方法loadImage(":8080/Struts2JQueryJson/test/one.png",R.id.imageOne);loadImage(":8080/Struts2JQueryJson/test/two.jpg",R.id.imageTwo);loadImage(":8080/Struts2JQueryJson/test/three.jpg",R.id.imageThree);loadImage(":8080/Struts2JQueryJson/test/four.png",R.id.imageFour); 可能,目前看不出和第一种的区别,这是因为我们现在加载的图片只有四张,如果我们加载的图片很多的话,区别还是比较明显的,但是仔细想想,这种方式还是有一点不足之处,那就是我们每次都需要访问网络来加载图片,,如果我们能够将已经加载的图片来缓存起来,那是多么的美好啊,那么我们的第三种模式就应运而生了。

线程池和内存缓存的模式:

首先新建一个AsyncImageLoader类,专门用来加载网络的图片的:

AsyncImageLoader.java

package com.example.sysnthreadpoolcache;import java.io.IOException;import java.lang.ref.SoftReference;import java.net.MalformedURLException;import java.net.URL;import java.util.HashMap;import java.util.Map;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import android.graphics.drawable.Drawable;import android.os.Handler;import android.widget.ImageView;public class AsyncImageLoader {// 为了加快速度,在内存中开启缓存(主要应用于重复图片较多时,或者同一个图片要多次被访问,比如在ListView时来回滚动)private Map<String,SoftReference<Drawable>>imageCache = new HashMap<String, SoftReference<Drawable>>();//定义缓存图片的map对象private ExecutorService service = Executors.newFixedThreadPool(4);//新建一个线程池,包含四个线程private Handler handler = new Handler();//对外部公开的接口public interface ImageCallback{// 注意 此方法是用来设置目标对象的图像资源public void imageLoaded(Drawable imageDrawable);}public Drawable loadDrawable(final String url,final ImageCallback callback){if (imageCache.containsKey(url)) {//如果缓存里边存在SoftReference<Drawable> drawableReference = imageCache.get(url);Drawable drawable = drawableReference.get();if (null != drawable) {return drawable;}}service.submit(new Runnable() {//// 缓存中没有图像,则从网络上取出数据,并将取出的数据缓存到内存中@Overridepublic void run() {// TODO Auto-generated method stubfinal Drawable drawable = loadImage(url);imageCache.put(url, new SoftReference<Drawable>(drawable));handler.post(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubcallback.imageLoaded(drawable);}});}});return null;}private Drawable loadImage(final String url) {// TODO Auto-generated method stubDrawable drawable = null;try {drawable = Drawable.createFromStream(new URL(url).openStream(),"haha.png");} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return drawable;}}我们的MainActivity代码也很简单,如下:

地球仍然转重,世间依旧善变,而我永远爱你。

handler加线程模式实现android应用的异步加载

相关文章:

你感兴趣的文章:

标签云: