Bitmap 二次采样三级缓存

来源:互联网 发布:淘宝账号要绑定手机吗 编辑:程序博客网 时间:2024/05/22 09:40

一、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 开发艺术探索》一书有详细描述