ListView异步加载图片

在应用开发中,经常用到ListView去加载数据,加载图片和文字是比较常见的,文字还好,图片从网络请求加载速度比较慢,所以需要把图片的加载放到另一个线程中去执行,执行完了再更新UI线程。以下列出一个我在项目中使用到的异步加载图片的解决方案,代码没有上全,给出核心部分。




大致思路是这样:

1.利用软引用来缓存图片Bitmap,用图片的URL作为缓存查找的Key;

2.设两级缓存,一级是SoftReference,二级是本地SD卡;

3.如果两级缓存都没取到图片,则从服务器获取,并加入缓存;

4.加载完后通过回调接口通知UI更新;




以下是异步加载的关键代码,其中一些工具类没有给出,自己实现就可以,比如HttpRequest是我自己写的一个类。




[java] view plaincopy
01.public class AsyncImageLoader { 
02. 
03.    //Cache for image(Type String is the URL of image,the second parameter is soft reference) 
04.    private HashMap<String, SoftReference<Bitmap>> imageCache = null; 
05.    private Activity context; 
06.     
07.    public AsyncImageLoader(Activity context){ 
08.        this.context = context; 
09.        imageCache = new HashMap<String, SoftReference<Bitmap>>(); 
10.    } 
11.     
12.    public Bitmap loadImage(final ImageView imageView,final String imageURL,final ImageCallBack imageCallBack){ 
13.         
14.        //If the cache contains the reference of bitmap then return 
15.        if (imageCache.containsKey(imageURL)) { 
16.            SoftReference<Bitmap> bitmapReference = imageCache.get(imageURL); 
17.            Bitmap bitmap = bitmapReference.get(); 
18.            if (bitmap != null) { 
19.                return bitmap; 
20.            } 
21.        } 
22.        //Second cache,search local SD card 
23.        else { 
24.            String fileName = StringUtil.namePicture(imageURL);//获取文件名 
25.            boolean isExist = SystemUtils.findPhotoFromSDCard(Constant.INFO_PATH, fileName); 
26.            if (isExist) {//是否在SD卡存在图片 
27.                Bitmap bitmap = SystemUtils.getPhotoFromSDCard(Constant.INFO_PATH, fileName); 
28.                return bitmap; 
29.            } 
30.             
31.        } 
32.         
33.        final Handler myHandler = new Handler(){ 
34.             
35.        @Override   
36.           <span style="white-space: pre;"> </span> public void handleMessage(Message msg)   
37.           <span style="white-space: pre;"> </span>{   
38.               <span style="white-space: pre;"> </span>imageCallBack.setImage(imageView, (Bitmap)msg.obj);   
39.           <span style="white-space: pre;"> </span>}   
40.        }; 
41.         
42.        //If the bitmap not exists in cache or SD card,then get it from net 
43.        new Thread(){ 
44.             
45.            @Override 
46.            public void run() { 
47.                // TODO Auto-generated method stub 
48.                boolean isNetwork = SystemUtils.checkNetwork(context); 
49.                if (isNetwork) { 
50.                    InputStream photoStream = HttpRequest.getImageStream(imageURL);//这里是我自己写的一个类,目的是通过URL地址从服务器获取图片输入流 
51.                    Bitmap bitmap; 
52.                    try { 
53.                        bitmap = ImageTools.getResizeBitmap(photoStream, 128, 128); 
54.                        if (bitmap != null) { 
55.                            String fileName = StringUtil.namePicture(imageURL); 
56.                            //Save image to SD card 
57.                            SystemUtils.savePhotoToSDCard(bitmap, fileName, Constant.INFO_PATH); 
58.                            //Put soft reference to cache 
59.                            imageCache.put(imageURL, new SoftReference<Bitmap>(bitmap)); 
60.                            //Send message to update UI 
61.                            Message message = myHandler.obtainMessage(0, bitmap); 
62.                            myHandler.sendMessage(message); 
63.                        } 
64.                    } catch (Exception e) { 
65.                        // TODO Auto-generated catch block 
66.                        e.printStackTrace(); 
67.                    } 
68.                } 
69.            } 
70.        }.start(); 
71.         
72.        return null; 
73.    } 
74.     
75.    /**
76.     * Interface for load image
77.     * @author Ryan
78.     *
79.     */ 
80.    public interface ImageCallBack{ 
81.        //Set image for imageview through bitmap 
82.        public void setImage(ImageView imageView,Bitmap bitmap); 
83.    } 
84.     
85.} 

在ListView的adapter的getView方法中:





[java] view plaincopy
01.Bitmap bitmap1 = asyncImageLoader.loadImage(viewHolder.imageView1, url1, new ImageCallBack() { 
02.                 
03.                @Override 
04.                public void setImage(ImageView imageView, Bitmap bitmap) { 
05.                    // TODO Auto-generated method stub 
06.                    imageView.setImageBitmap(bitmap); 
07.                } 
08.            }); 
09.             
10.            if (bitmap1 != null) { 
11.                viewHolder.imageView1.setImageBitmap(bitmap1); 
12.            }else { 
13.                viewHolder.imageView1.setImageResource(R.drawable.image_bg); 
14.            } 

其中asyncImageLoader是在adapter的构造方法中初始化的,形成一个缓存。通过这个机制就可以实现ListView的图片异步加载,在用户体验上比直接加载要感觉好很多,那样会造成界面卡顿。这里是加载一张图片的情况,如果ListView的item中的图片是不定的,有可能是一张、两张、三张,该用什么方式呢,大家

猜你喜欢

转载自arm10504.iteye.com/blog/2065853