Glide原理之史上最全的(二)

Glide 缓存原理
Glide 使用了三级缓存机制,图片的缓存分为内存、磁盘和来源,也就是从内存获取不到图片时,再去磁盘获取图片,从磁盘获取不到图片时,再从图片来源获取图片。
三级缓存的优势在于节省流量和内存,如果不用三级缓存,每次都从服务端获取图片的话,图片消耗的流量就会非常多,如果把所有图片都放在内存的话,那就有可能发生 OOM 。
下面我们来看下 Glide 的内存缓存原理、磁盘缓存原理和磁盘缓存策略。
3.1 Glide 内存缓存原理
前面提到 Engine 的 load() 方法会先在内存缓存中查找 Key 对应的资源,没有的话再启动新的解码任务。
这里说的内存缓存就是 MemoryCache,MemoryCache 是一个接口,它的实现类是 LruResourceCache。
LruResourceCache 不仅实现了 MemoryCache 接口,而且还是 LruCache 的子类,具体的内存缓存实现是在 LruCache 中。
Glide原理之史上最全的(二)_第1张图片
在 LruCache 的 put() 方法中,首先会判断要保存的元素大小是否大于缓存最大值,如果是的话,则不进行保存,如果不是的话,则把当前容量加上元素的大小,并把该元素放入缓存。
LruCache 比较特别的就是它的 trimToSize() 方法和 LinkedHashMap 的 accessOrder 属性。

  1. trimToSize()
    LruCache 在用 put() 方法保存新的元素时,它会通过 trimToSize() 方法移除最近最少使用的元素。
  2. accessOrder
    LruCache 中是用 LinkedHashMap 保存数据的,并且这个 LinkedHashMap 的 accessOrder 的值为 true,也就是每一次获取 LinkedHashMap 中的元素时,这个元素都会被移到链表的尾端。
    3.2 Glide 磁盘缓存原理
    Glide 是用 DiskCache 保存图片文件的,DiskCache 是一个接口,这个接口中还定义了 Factory 和 Writer 两个接口,Writer 只是对 ResourceEncoder 的封装。
    下面我们就来看看 DiskCache 和 DiskCache.Factory 的具体实现。
    3.2.1 DiskLruCache
    DiskCache 有两个实现类, DiskCacheAdapter 和 DiskLruCacheWrapper,DiskCacheAdapter 只是一个空实现。
    从名字可以看得出来 DiskLruCacheWrapper 是对 DiskLruCache 的封装,具体的实现是在 DiskLruCache 中,DataCacheGenerator 和 ResourceCacheGenerator 都是用的 DiskLruCache 来获取磁盘缓存数据的。
  3. Entry
    和 LruCache 一样,DiskLruCache 中也有一个 LinkedHashMap ,这个 HashMap 的 Key 的类型为 String,Value 的类型为 Entry,从缓存中获取到的图片文件会放在 Entry的 cleanFiles 字段中。
  4. Editor
    当图片加载进入编码阶段时,DecodeJob 会通过编码管理器调用 DiskLruCacheWrapper 的 put() 方法保存图片文件。
    在 DiskLruCacheWrapper 的 put() 方法中,会通过 DiskCache 的缓存编辑器 Editor 获取图片文件,获取到图片文件后,就会用 Writer 把文件写入本地,写完后再调用 Editor 的 commit() 方法,把清理缓存的回调提交到清理线程池中。
  5. 清理资源
    DiskLruCache 中有一个执行清理资源任务的线程池,线程池的线程数最多为 1,
    这个线程池要执行的任务为 cleanupCallback 回调,这个回调会执行 trimToSize() 方法,为的就是把最近最少使用的文件清除掉。
    3.2.2 DiskCache.Factory
    在 DiskCache 中有一个 Factory 工厂接口,这个接口用在了 Engine 的 LazyDiskCacheProvider 中。
    在 Factory 接口中,定义了默认的磁盘缓存大小为 250M,默认的缓存目录名称为 “image_manager_disk_cache” 。
    Factory 主要有下面 2 个实现类。

ExternalPreferredCacheDiskCacheFactory
用的是 getExternalCacheDir() 。
对应的目录是 /data/user/0/包名/cache/image_manager_disk_cache。

InternalCacheDiskCacheFactory
用的是 context.getCacheDir() 。
对应的目录是 /data/user/0/包名/cache 。

默认情况下 Glide 用的是 InternalCacheDiskCacheFactory ,如果想把图片放在外部缓存目录的话,可以在自定义的 GlideModule 设置 DiskCache 。
3.3 Glide 磁盘缓存策略
在加载图片时,我们可以用 diskCacheStratgy() 方法设置图片在磁盘的缓存策略,这个选项传入的参数类型为抽象类 DiskCacheStrategy。
磁盘缓存策略涉及到 Glide 的数据源类型 DataSource 和编码策略 EncodeStratefy,编码策略前面讲过了,下面我们先来看看数据源 DataSource。
3.3.1 五种数据源
Glide 中定义了下面 5 种数据源 DataSource。

LOCAL
设备上有的数据,比如 App 内置的 Drawable 也属于 LOCAL ;

REMOTE
从服务端拿到的数据;

DATA_DISK_CACHE
从缓存中取出来的原始数据;

RESOURCE_DISK_CACHE
从缓存中取出来的图片资源;

MEMORY_CACHE
从内存缓存中取出来的数据;

3.3.2 四个抽象方法
DiskCacheStrategy 有下面 4 个抽象方法,这个 4 个方法的返回值都是布尔值。

你可能感兴趣的:(操作技巧,android,android,studio)