Glide ② — 缓存机制

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Glide ② — 缓存机制相关的知识,希望对你有一定的参考价值。

参考技术A

阅读本文需要先了解 Glide加载流程

首先介绍一下Glide中对图片资源的封装类: EngineResource

在活动缓存中,使用了一个map用来存放EngineResource对象,这里需要注意一个操作,就是这个EngineResource对象是用WeakReference包裹的,并且通过ReferenceQueue监听了EngineResource的回收,在回收的时候会清理当前的活动缓存内容;
下面分析一下源码是如果实现的:
首先,自定义一个WeakReference类,将key和resource传进入(用于在WeakReference回收的时候释放),传入一个ReferenceQueue对象,用于监听WeakReference回收

开启一个子线程,在循环中监听ReferenceQueue的返回值,通过这个返回值,判断WeakReference有没有回收,监听的方法是ReferenceQueue.remove(),这是一个阻塞方法;所以要开子线程;

LruResourceCache继承了LruCache类,关于LruCache类,简单提一下,具体的可以参考我之前的博客 LruCache实现 ,LruCache继承了LinkedHashMap,LinkedHashMap有一个特点,就get后的数据会移动到队列,这就是Lru思想:固定一个容量,put的时候如果超过容量了,将最后一个节点删除,get的时候将get的这个节点移动到队列的头部;

onItemEvicted()方法是LruCache的一个空方法,调用的时机是在put的时候判断是否超过容量,如果超过容量了,就淘汰最后一个节点,并调用这个方法;

活动缓存和内存缓存都是缓存在内存中的,活动缓存缓存的是正在使用的图片资源,当图片不使用时会放到内存缓存中,提出活动缓存的目的:单一的内存缓存由于Lru的淘汰机制会导致图片加载不稳定

首先介绍一个磁盘缓存方案DiskLruCache(非Google官方编写,但获得官方认证),关于这个磁盘缓存方案的理解可以看郭林的这片文章:
Android DiskLruCache完全解析,硬盘缓存的最佳方案

从上一篇文章知道,Glide加载操作是通过 Engine 来驱动的

Engine的load()中,首先尝试从 活动缓存 和 内存缓存 获取缓存,如果没有缓存再启动EngineJob和DecodeJob; 上面介绍了缓存的获取,下面看一下缓存的存放,肯定是在获取到图片后的回调中存放的

在DecodeJob获取到图片数据后,会回调很多接口,在回调中会将其放入 活动缓存 ,当图片不在使用的时候,就会放入内存缓存,根据上面介绍的活动缓存规则,当 EngineResource 计数为0时就应该放入内存缓存;

当资源引用为0,回调onResourceReleased(),从活动缓存移除,放入内存缓存;

上面介绍了活动缓存和内存缓存的存放和获取,下面看一看磁盘缓存的存取;

还记得 DataFetcherGenerator 接口吗?这个接口是DecodeJob用于获取数据的,有三个具体的实现:

我们在上一篇具体介绍的是网络文件的获取,这里的磁盘缓存使用的就是 DataCacheGenerator(缓存文件) 这个Generator了

上篇文章知道DecodeJob是一个Runnable任务,在run()会调用runWrapped(),在runWrapped()中会做三种事情:

在runWrapped()的解码操作中会执行decode(),在decode()中,会disk put操作;

Glide的磁盘缓存是基于DiskLruCache 实现的,Glide直接使用的是DiskLruCacheWrapper对象对DiskLruCache 的封装;

以上是关于Glide ② — 缓存机制的主要内容,如果未能解决你的问题,请参考以下文章

Android-Glide的缓存机制

Glide 缓存机制

Glide 缓存机制

Glide 缓存机制

Glide 缓存机制

Glide 缓存机制及源码