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


    首先说一下,android系统加载大量图片系统内存溢出的3中解决方法:

    (1)从网络或本地加载图片的时候,只加载缩略图。这个方法的确能够少占用不少内存,可是它的致命的缺点就是,因为加载的是缩略图,所以图片失真比较严重,对于对图片质量要求很高的应用,可以采用下面的方法

    /**

     *按照图片路径加载

     *@param path图片资源的存放路径

     *@param scalSize缩小的倍数

     *@return

     */

    public static Bitmap loadResBitmap(String path, int scalSize){

      BitmaoFactory.Options options = new BitmapFactory.Options();

      options.inJustDecodeBounds = false;

      options.inSampleSize = scalSize;

      Bitmap bmp = BitmapFactory.decodeFile(path, options);

      reuturn bmp;

    }

    (2)运用JAVA的软引用,进行图片缓存,将经常需要加载的图片,存放在缓存里,避免反复加载。

    (3)及时销毁不再使用的Bitmap对象。

    if (bitmap != null && b!itmap.isRecycled()){

      bitmap.recycle();

      bitmap = null; // recycle()是个比较漫长的过程,设为null,然后在最后调用System.gc(),效果能好很多

      System.gc();

    }

     

    好了,以上是主题之前的知识补充,以下是这篇blog的主要内容。HashMap<String, SoftReference<Drawable>> imageCache 关于SoftReference这个类多少知道些机制,只是处在会用的阶段(这是不够的)。

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

      

        实现代码片段:

       

    [java]
    package com.Tianyou.Mobile.Common; 
     
    import java.io.IOException; 
    import java.io.InputStream; 
    import java.lang.ref.SoftReference; 
    import java.net.MalformedURLException; 
    import java.net.URL; 
    import java.util.HashMap; 
     
    import com.Tianyou.Mobile.Util.MyUtil; 
     
    import android.graphics.Bitmap; 
    import android.graphics.drawable.BitmapDrawable; 
    import android.graphics.drawable.Drawable; 
    import android.os.Handler; 
    import android.os.Message; 
     
    /***
     * 异步加载图片 缓存的实现
     * 
     * @author jia
     * 
     */ 
    public class AsyncImageLoader { 
        // 软引用 
        private HashMap<String, SoftReference<Drawable>> imageCache; 
     
        public AsyncImageLoader() { 
            imageCache = new HashMap<String, SoftReference<Drawable>>(); 
        } 
     
        /***
         * 下载图片
         * 
         * @param imageUrl
         *            图片地址
         * @param imageCallback
         *            回调接口
         * @return
         */ 
        public Drawable loadDrawable(final String imageUrl, 
                final ImageCallback imageCallback) { 
            if (imageCache.containsKey(imageUrl)) { 
                SoftReference<Drawable> softReference = imageCache.get(imageUrl); 
                Drawable drawable = softReference.get(); 
                if (drawable != null) { 
                    return drawable; 
                } 
            } 
            final Handler handler = new Handler() { 
                public void handleMessage(Message message) { 
                    imageCallback.imageLoaded((Drawable) message.obj, imageUrl); 
                } 
            }; 
            // 开启线程下载图片 
            new Thread() { 
                @Override 
                public void run() { 
                    Drawable drawable = loadImageFromUrl(imageUrl); 
                    // 将下载的图片保存至缓存中 
                    imageCache.put(imageUrl, new SoftReference<Drawable>(drawable)); 
                    Message message = handler.obtainMessage(0, drawable); 
                    handler.sendMessage(message); 
                } 
            }.start(); 
            return null; 
        } 
     
        /***
         * 根据URL下载图片(这里要进行判断,先去本地sd中查找,没有则根据URL下载,有则返回该drawable)
         * 
         * @param url
         * @return
         */ 
        public static Drawable loadImageFromUrl(String imageURL) { 
     
            Bitmap bitmap = MyUtil.GetBitmap(imageURL, 100); 
            Drawable drawable = new BitmapDrawable(bitmap); 
            return drawable; 
     
        } 
     
        // 回调接口 
        public interface ImageCallback { 
            public void imageLoaded(Drawable imageDrawable, String imageUrl); 
        } 
     

         上面这个类斯通见惯了,大部分都是这样实现的,我现在要讲一点,也是迷惑我很久了一点(回调接口运用)本人基础不好,所以卡在这里了,
         在listview中的getview方法中要调用这个方法:

         代码片段:

    [java] 
    public Drawable getDrawable(AsyncImageLoader asyncImageLoader, 
                String imageUrl, final ImageView imageView) { 
            Drawable drawable = asyncImageLoader.loadDrawable(imageUrl, 
                    new ImageCallback() { 
                        @Override 
                        public void imageLoaded(Drawable imageDrawable, 
                                String imageUrl) { 
                            if (imageDrawable != null) 
                                imageView.setImageDrawable(imageDrawable); 
                            else 
                                imageView.setImageResource(R.drawable.u6_normal); 
                        } 
                    }); 
            return drawable; 
        } 
      这个方法作用:获取软用中的图片,其实在我们首次进入listview中的时候,软应用是不起作用的,只是用来下载图片保存至sd卡和软引用中.这个方法就是执行了这些操作,对于参数imageView 就是在要把获取的drawable设置进去.
       执行的顺利:首先我们调用的是loadDrawable这个方法,然后查找软引用中有没有该drawable,没有的话则线程下载,下载ok后会执行 handleMessage中imageCallback.imageLoaded((Drawable) message.obj, imageUrl);然后执行我们已经实现了这个接口.

         在getiview 中执行代码片段:

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

    PS:其次,可参考http://www.2cto.com/kf/201303/194546.html

  • 相关阅读:
    替换Srun3000解决掉网问题
    了解Equals所发生的事情
    WPF自定义TextBox及ScrollViewer
    自制多类编码转换工具
    .NET4.5之自制多LRC转SRT小工具
    JAVA_list总结
    记一次线程Timer导致的线程安全问题修正
    JAVA_匿名内部类
    JAVA_map总结
    JAVA_闭包
  • 原文地址:https://www.cnblogs.com/zzcc/p/3896571.html
Copyright © 2020-2023  润新知