图片缓存、Glide总结

Bitmap

在安卓中指一张图片,支持从文件系统、资源、输入流、字节数组加载一个bitmap对象,对应底层的native方法。
通过BitmapFactory.Options采样缩放,避免OOM。InSampleSize:采样率,同时作用于宽高。InSampleSize=2,总的大小是原来的1/4

LruCache

最近最少使用算法,缓存满时,优先淘汰那些近期最少使用的缓存对象。有LruCache和DiskLruCache两种。
LruCache泛型类 LruCache<String, Bitmap>,采用一个LinkedHashMap以强引用的方式存储外界缓存对象,线程安全。
强引用:直接的对象引用
软引用:内存不足时会被GC回收
弱引用:随时会被GC回收
Java中HashMap是一个哈希表,hashmap本身是无顺序的,而LinkedHashMap是有序的,LinkedHashMap使用双向链表的形式来存储MapEntry的
LruCache算法内部其实是一个队列的形式在存储数据,先进来的数据放在队列的尾部,后进来的数据放在队列头部。如果要使用数据,就在把数据放到队列头部。如果要存储数据,但是发现数据已经满了,这是就删除队列尾部的数据,然后缓存新数据。

Bitmap bitmap = null;
        //获取运行内存大小的八分之一
        int memory = (int)Runtime.getRuntime().totalMemory() / 1024;
        int cache = memory / 8;
        bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);
        LruCache<String,Bitmap> lruCache = new LruCache<String,Bitmap>(cache){
            @Override
            protected int sizeOf(String key, Bitmap bitmap) {
                return bitmap.getRowBytes() * bitmap.getHeight() / 1024;
            }
        };
        //将数据存储进入缓存
        lruCache.put("cacheBitmap",bitmap);
 
        Bitmap cacheBitmap = lruCache.get("cacheBitmap");
        //在使用的时候判断是否图片为空,因为有可能图片因为内存空间满了而被剔除
        if (cacheBitmap != null){
            //TODO
        }

BitmapRegionDecoder

在不压缩的情况下加载高清大图,按照原图尺寸加载,那么屏幕肯定是不够大的,并且考虑到内存的情况,不可能一次性整图加载到内存中,所以肯定是局部加载,那么就需要用到一个类BitmapRegionDecoder。
BitmapRegionDecoder主要用于显示图片的某一块矩形区域。屏幕显示不完,添加一个上下左右拖动的手势,让用户可以拖动查看
1.传入需要处理的图片
BitmapRegionDecoder bitmapRegionDecoder = BitmapRegionDecoder.newInstance(inputStream, false);
2.显示指定的区域
bitmapRegionDecoder.decodeRegion(rect, options);
参数一是一个rect,参数二是BitmapFactory.Options

ImagerLoader:

图片的同步加载、异步加载、图片压缩、内存缓存、磁盘缓存、网络拉取
(只有当两级缓存都不可用时才加载网络, 依次从内存、磁盘、网络拿bitmap,拿到了就return,否则就下一步)
手机的内存是系统根据进程个数分配的。1/8内存作为LruCache空间。

列表优化:

a.不要在getView里面做耗时操作,应该用异步的方式
b.滑动停止时异步请求网络
c.开启硬件加速android:hardwareAccelerated="true"

Glide(https://www.jianshu.com/p/86b4456066a9)

1.使用 Glide.with(this).load(url).into(imageView)

Glide不会直接将图片的完整尺寸全部加载到内存中,自动判断ImageView的大小,然后只将这么大的图片像素加载到内存当中,
节省内存开支。不用担心图片内存浪费,甚至是内存溢出的问题。

2.内存缓存

作用是防止重复将图片数据读取到内存当中。默认情况下,Glide自动就是开启内存缓存的。skipMemoryCache(true)禁用缓存。
Glide决定缓存Key的参数有10个,10个参数通过EngineKeyFactory的buildKey()方法,构建一个EngineKey(缓存Key)对象,
用override()方法改变了一下图片的width或者height,也会生成一个完全不同的缓存Key。

Glide内存缓存结合LruCache算法和弱引用的机制。通过两个方法loadFromCache(LruCache算法)和loadFromActiveResources(弱引用)
正在使用中的图片使用弱引用来进行缓存,不在使用中的图片使用LruCache来进行缓存的功能。

3.磁盘缓存

作用是防止重复从网络下载和读取数据。
diskCacheStrategy(DiskCacheStrategy.NONE)禁用磁盘缓存。默认DiskCacheStrategy.RESULT表示只缓存转换过后的图片
硬盘缓存的实现LruCache算法,Glide是使用的自己编写的DiskLruCache工具类,和DiskLruCache实现原理类似。

4.预加载preload()方法

如果使用preload(),最好将diskCacheStrategy指定成DiskCacheStrategy.SOURCE。因为preload()默认预加载原始图片大小,
而into()则默认会根据ImageView控件大小动态决定加载图片的大小。这样做了保证Glide一定会去读取刚才预加载的图片缓存。
不这样做很容易会造成在预加载完成之后,使用into()却还要从网络请求图片。
Glide还有listener()、transform(图片变化功能)、GlideModule(自定义模块)等方法。
Glide使用的是基于原生HttpURLConnection进行订制的HTTP通讯组件。