android Listview 软引用SoftReference异步加载图片

时间:2022-08-27 15:40:57

    之前总是不太理解,今天认真的推敲下,记录下来方便以后用到.

    HashMap<String, SoftReference<Drawable>> imageCache 关于SoftReference这个类多少知道些机制,会用就ok了。

    机制:简单来说,她会帮助我们管理内存,防止内存溢出,另外一点也就相当于map,临时缓存些图片drawable让我们可以直接引用,很好了解决了OOM异常.

   

    实现代码片段:

[java] view plaincopy
  1. package com.Tianyou.Mobile.Common;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.lang.ref.SoftReference;  
  6. import java.net.MalformedURLException;  
  7. import java.net.URL;  
  8. import java.util.HashMap;  
  9.   
  10. import com.Tianyou.Mobile.Util.MyUtil;  
  11.   
  12. import android.graphics.Bitmap;  
  13. import android.graphics.drawable.BitmapDrawable;  
  14. import android.graphics.drawable.Drawable;  
  15. import android.os.Handler;  
  16. import android.os.Message;  
  17.   
  18. /*** 
  19.  * 异步加载图片 缓存的实现 
  20.  *  
  21.  * @author jia 
  22.  *  
  23.  */  
  24. public class AsyncImageLoader {  
  25.     // 软引用  
  26.     private HashMap<String, SoftReference<Drawable>> imageCache;  
  27.   
  28.     public AsyncImageLoader() {  
  29.         imageCache = new HashMap<String, SoftReference<Drawable>>();  
  30.     }  
  31.   
  32.     /*** 
  33.      * 下载图片 
  34.      *  
  35.      * @param imageUrl 
  36.      *            图片地址 
  37.      * @param imageCallback 
  38.      *            回调接口 
  39.      * @return 
  40.      */  
  41.     public Drawable loadDrawable(final String imageUrl,  
  42.             final ImageCallback imageCallback) {  
  43.         if (imageCache.containsKey(imageUrl)) {  
  44.             SoftReference<Drawable> softReference = imageCache.get(imageUrl);  
  45.             Drawable drawable = softReference.get();  
  46.             if (drawable != null) {  
  47.                 return drawable;  
  48.             }  
  49.         }  
  50.         final Handler handler = new Handler() {  
  51.             public void handleMessage(Message message) {  
  52.                 imageCallback.imageLoaded((Drawable) message.obj, imageUrl);  
  53.             }  
  54.         };  
  55.         // 开启线程下载图片  
  56.         new Thread() {  
  57.             @Override  
  58.             public void run() {  
  59.                 Drawable drawable = loadImageFromUrl(imageUrl);  
  60.                 // 将下载的图片保存至缓存中  
  61.                 imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));  
  62.                 Message message = handler.obtainMessage(0, drawable);  
  63.                 handler.sendMessage(message);  
  64.             }  
  65.         }.start();  
  66.         return null;  
  67.     }  
  68.   
  69.     /*** 
  70.      * 根据URL下载图片(这里要进行判断,先去本地sd中查找,没有则根据URL下载,有则返回该drawable) 
  71.      *  
  72.      * @param url 
  73.      * @return 
  74.      */  
  75.     public static Drawable loadImageFromUrl(String imageURL) {  
  76.   
  77.         Bitmap bitmap = MyUtil.GetBitmap(imageURL, 100);  
  78.         Drawable drawable = new BitmapDrawable(bitmap);  
  79.         return drawable;  
  80.   
  81.     }  
  82.   
  83.     // 回调接口  
  84.     public interface ImageCallback {  
  85.         public void imageLoaded(Drawable imageDrawable, String imageUrl);  
  86.     }  
  87.   
  88. }  
     上面这个类斯通见惯了,大部分都是这样实现的,我现在要讲一点,也是迷惑我很久了一点(回调接口运用)本人基础不好,所以卡在这里了,

     在listview中的getview方法中要调用这个方法:

     代码片段:

[java] view plaincopy
  1. public Drawable getDrawable(AsyncImageLoader asyncImageLoader,  
  2.             String imageUrl, final ImageView imageView) {  
  3.         Drawable drawable = asyncImageLoader.loadDrawable(imageUrl,  
  4.                 new ImageCallback() {  
  5.                     @Override  
  6.                     public void imageLoaded(Drawable imageDrawable,  
  7.                             String imageUrl) {  
  8.                         if (imageDrawable != null)  
  9.                             imageView.setImageDrawable(imageDrawable);  
  10.                         else  
  11.                             imageView.setImageResource(R.drawable.u6_normal);  
  12.                     }  
  13.                 });  
  14.         return drawable;  
  15.     }  
  这个方法作用:获取软用中的图片,其实在我们首次进入listview中的时候,软应用是不起作用的,只是用来下载图片保存至sd卡和软引用中.这个方法就是执行了这些操作,对于参数imageView 就是在要把获取的drawable设置进去.

   执行的顺利:首先我们调用的是loadDrawable这个方法,然后查找软引用中有没有该drawable,没有的话则线程下载,下载ok后会执行handleMessage中imageCallback.imageLoaded((Drawable) message.obj, imageUrl);然后执行我们已经实现了这个接口.

     在getiview 中执行代码片段:

     

[java] view plaincopy
  1. Drawable drawable = getDrawable(asyncImageLoader, Image_L,  
  2.                 holder.iv_image);  
  3.           
  4.         if(drawable!=null)  
  5.             holder.iv_image.setImageDrawable(drawable);  
   当我们下滑动后,然后在上滑动的时候软应用起到了效果,效率很快哦,可以和新浪聘美了,呵呵,玩笑,要优化的地方还很多.