Bitmap 二次采样三级缓存

一、Bitmap

1.1 Bitmap 图片,加载的方式一般有四种

方法名 说明
BitmapFactory.decodeByteArray() 从字节数据中加载
BitmapFactory.decodeFile() 从文件中加载
BitmapFactory.decodeFileDescriptor() 从“文件描述“中加载
BitmapFactory.decodeResource() 从资源文件中加载
BitmapFactory.decodeStream() 从输入流中加载

1.2 Bitmap的二次采样

什么是二次采样呢?简单来说就是将原来的图片进行压缩,是的它的大小发生变化但是不会出现其他症状(变形,失帧等),从而使的在我们的开发中避免Bitmap过大而出现的OOM,
那怎么搞呢?又一个BitmapFactory.Options类可以将图片进行目标空间的相吻合的尺寸, BitmapFactory.Options 的这个参数inSampleSize 就是采样率,官方的文档指出采样率取值应该是2的指数 (加入设定的不是2 的指数 ,系统会向小取整 2的指数的数),例如 n ,那么采样后的图片的 宽高均为原图片大小的1/n
下面就是二次采样的代码


/**
     * 图片的二次采样
     *
     * @param resources
     * @param width
     * @param height
     */
    private Bitmap decodeSampledBitmapFromResource(Resources resources, int resId, int width, int height) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        //只解析图片的宽高 而不加载真正的图片
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(resources, resId, options);

        options.inSampleSize = calculateInSampleSize(options, width, height);
        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(resources,resId,options);

    }

 /**
     *  计算inSampleSize 值
     * @param options
     * @param width
     * @param height
     * @return
     */
    private int calculateInSampleSize(BitmapFactory.Options options, int width, int height) {
        if (width == 0 || height == 0) {
            return 1;

        }
        //图片的原始宽高
        int outHeight = options.outHeight;
        int outWidth = options.outWidth;

        int inSampleSize = 1;
        //如果宽和高有一个不符合 就进行调整
        if (outHeight > height || outWidth > width) {
            // inSampleSize 为 1 没有作用,使从 2 开始增加
            int newWidth = outWidth / 2;
            int newHeight = outHeight / 2;
            while ((newHeight / inSampleSize) >= height && (newWidth / inSampleSize) >= width) {
                inSampleSize *= 2;
            }

        }
        return inSampleSize;

    }

二、CaChe

一般情况下,在有关于Bitmap 的时候我们会讲图片的二次采样,三级缓存,二次采样已经介绍过了,现在就看一下Cache ,要做的三级缓存,为什么我们要做三级缓存呢?因为在移动设备中,每个人的流量都是宝贵的,像现在的4G流量,你要是不做缓存,每次去网络请求,那还不得把使用的人气死,打开一个界面停机了(哈哈,夸张了,但是缓存我们是必须要做的)目的很明确,就是为用户节省流量,还有一个作用就是,你要在程序中获取一张图片的最快方式肯定是从本地获取的,这也就是为什么要缓存的原因之一,我门在开发的时候一般将缓存做成双缓存(此双缓存不是自定义View中的哪个双缓存哦),知识这种叫法哈,然后是怎么双缓存的呢,先看图
这里写图片描述
说明:我们在使用图片的时候先去在缓存中查找,看一下有没有要使用的目标图片,如果有,进行使用,没有继续到存储中查找,同样,有的话使用,没有的话再去网络上下载,下载之后呢?将它先使用,再进行缓存、存储,从而为下一此使用进行了相应的存储和缓存,

三、Cache Problem ?

(口述问号懵逼脸)
为什么手缓存的问题呢?

  1. 缓存分为哪几种缓存,到底用那种
  2. 上面没有说具体的缓存的策略和使用的方法
  3. 缓存满了怎么办?

下面我就带者这几个问题来看

3.1 Android 中的缓存策略

目前最常用的一种缓存算法是LRU(Least Recently Used):最近最少使用算法
核心:它的核心就是当缓存满的时候,优先清除最近最少使用的对象,
采用LRU算法的缓存有两种:LruCache 和 DiskLruCache

3.1.1 LruCache

LruCache 是Android 3.1 提供的一个缓存类,通过v4 包兼容到早期的Android 版本,LruCache 是一个泛型类,内部采用的是一个LinkedHashMap 以强引用的方式存储外界的缓存对象,有get和put两种方法完成缓存的获取和添加,在这里要强调一下强、软、弱引用的区别

名称 说明
直接的对象应用
当一个对象只有软引用存在时,系统内存不足的时候该对象会被gc回收
当一个对象只有弱应用的时候,此对象会随时被gc回收
此对象会随时被gc回收

LruCache 实现成安全的

3.1.2 DiskLruCache

DiskLruCache 用于实现存储设备缓存,即磁盘缓存,它通过将缓存对象写入文件系统从而实现缓存。
DiskLruCache受到了Android 官方的推荐,但是它不是Android SDK的一部分它的源码可以从https://android.googlesource.com/platform/libcore/+/android-4.1.1_r1/luni/src/main/java/libcore/io/DiskLruCache.java 网址获取,但是这上边下载的源码不能直接使用,需要修改里面的一些东西,当然所有要修改的东西还是在上面的连接中,
《Android 开发艺术探索》一书有详细描述

发布了53 篇原创文章 · 获赞 20 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_32648731/article/details/77715910