美文网首页
十、性能优化-优化Bitmap资源

十、性能优化-优化Bitmap资源

作者: 你的益达233 | 来源:发表于2020-01-28 15:12 被阅读0次

    背景:Android系统分配给每个应用程序的内存有限,而图片资源非常消耗内存(即Bitmap)
    原因:若对Bitmap的使用与内存管理不当,则可能引发内存溢出,从而导致程序崩溃

    Bitmap占多大的内存?
    bitmap.getAllocationByteCount(); 或者
    bitmap.getByteCount();

    加载Bitmap的时候,通常要做这几件事

    一、根据分辨率适配与缩放图片

    1. 设置多套图片资源
      如果项目大小允许,至少在xh/xxh/xxxh中都放置图片,然后通过BitmapFactory.decodeResource获取

    2. 缩放图片比例进行压缩,按图片分辨率需求加载,用inSampleSize
      示例代码:

       BitmapFactory.Options opts = new BitmapFactory.Options();
       opts.inSampleSize = 4;
       Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);  
      

    二、按需选择合适的解码方式:options.inPreferredConfig

    优化原因:不同的图片解码方式对应的内存占用大小相差很大
    知识点:

    1. ARGB_4444: 基本不用,因为图片比较失真

    2. 示例ARGB_8888: 32位的ARGB位图,由4个8位组成(即32位),每个像素占8位,即A=8,R=8,G=8,B=8。 8+8+8+8 = 32位= 4个字节。即1个像素占4个字节
      示例:若1张480*800的图片,格式是ARGB_8888,将占1536000字节,即1500KB的内存
      3.默认使用解码方式:ARGB_8888
      特别注意:PNG图片设置无效
      示例代码:

      BitmapFactory.Options options1 = new BitmapFactory.Options();
      options1.inPreferredConfig = Bitmap.Config.RGB_565;
      Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher,options1);

    四、使用完毕后释放图片资源

    优化原因:使用完毕后若不释放图片资源,容易造成内存泄漏,从而导致内存溢出
    优化方案:
    在 Android2.3.3(API 10)前,调用 Bitmap.recycle()方法
    在 Android2.3.3(API 10)后,采用软引用(SoftReference)
    示例代码:

        View view = findViewById(R.id.button);
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
    Drawable drawable = new BitmapDrawable(bitmap);
    SoftReference<Drawable> drawableSoftReference = 
                                                new SoftReference<Drawable>(drawable);
        Drawable bgdrawable = drawableSoftReference.get();
    if(bgdrawable != null) {
        view.setBackground(bgdrawable);
    }
    

    需要注意的是,在垃圾回收器对这个Java对象回收前,SoftReference类所提供的get方法会返回Java对象的强引用,一旦垃圾线程回收该Java对象之后,get方法将返回null。所以在获取软引用对象的代码中,一定要判断是否为null,以免出现NullPointerException异常导致应用崩溃

    三、设置图片缓存

    优化原因:重复加载图片资源消耗太多资源(cpu,内存与流量)
    优化方案:使用三级缓存机制或者软引用
    三级缓存机制:内存缓存 - 本地缓存(硬盘、数据库或文件) - 网络缓存

    为什么要使用三级缓存
    假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量。在当前的状况下,对于非wifi用户来说,流量还是很贵的,一个很耗流量的应用,其用户数量级肯定要受到影响。
    特别是,当我们想要重复浏览一些图片时,如果每一次浏览都需要通过网络获取,流量的浪费可想而知

    什么是三级缓存:

    网络缓存, 不优先加载, 速度慢,浪费流量
    本地缓存, 次优先加载, 速度快
    内存缓存, 优先加载, 速度最快
    

    三级缓存原理:
    首次加载App时,通过网络交互来获取图片,之后将图片保存到本地SD卡和内存中
    之后运行App时,优先访问内存中的图片缓存,若内存中没有,则加载本地SD卡中的,如果SD卡中没有,则加载网络的
    内存缓存示例代码
    关键代码LruCache<String,Bitmap>

    /**
     * 三级缓存之内存缓存
     */
    public class MemoryCacheUtils {
    
        // private HashMap<String,Bitmap> mMemoryCache=new HashMap<>();//1.因为强引用,容易造成内存溢出,所以考虑使用下面弱引用的方法
        // private HashMap<String, SoftReference<Bitmap>> mMemoryCache = new HashMap<>();//2.因为在Android2.3+后,系统会优先考虑回收弱引用对象,官方提出使用LruCache
        private LruCache<String,Bitmap> mMemoryCache;
    
        public MemoryCacheUtils(){
            long maxMemory = Runtime.getRuntime().maxMemory()/8;//得到手机最大允许内存的1/8,即超过指定内存,则开始回收
            //需要传入允许的内存最大值,虚拟机默认内存16M,真机不一定相同
            mMemoryCache=new LruCache<String,Bitmap>((int) maxMemory){
                //用于计算每个条目的大小
                @Override
                protected int sizeOf(String key, Bitmap value) {
                    int byteCount = value.getByteCount();
                    return byteCount;
                }
            };
    
        }
    
        /**
         * 从内存中读图片
         * @param url
         */
        public Bitmap getBitmapFromMemory(String url) {
            //Bitmap bitmap = mMemoryCache.get(url);//1.强引用方法
            /*2.弱引用方法
            SoftReference<Bitmap> bitmapSoftReference = mMemoryCache.get(url);
            if (bitmapSoftReference != null) {
                Bitmap bitmap = bitmapSoftReference.get();
                return bitmap;
            }
            */
            Bitmap bitmap = mMemoryCache.get(url);
            return bitmap;
    
        }
    
        /**
         * 往内存中写图片
         * @param url
         * @param bitmap
         */
        public void setBitmapToMemory(String url, Bitmap bitmap) {
            //mMemoryCache.put(url, bitmap);//1.强引用方法
            /*2.弱引用方法
            mMemoryCache.put(url, new SoftReference<>(bitmap));
            */
            mMemoryCache.put(url,bitmap);
        }
    }
    

    图片三级缓存这个,现在基本都是用成熟的图片框架Glide或者picasso
    针对Glide的skipMemoryCache(false)//启动内存缓存 diskCacheStrategy() //硬盘缓存策略

    参考:https://www.jianshu.com/nb/21401973

    相关文章

      网友评论

          本文标题:十、性能优化-优化Bitmap资源

          本文链接:https://www.haomeiwen.com/subject/rntmthtx.html