Glide version is 4.8.0
Glide拥有三级缓存,分别为
- 当前正在使用得资源缓存(ActiveResources)
- 内存缓存(LruCache)
- 磁盘缓存(DiskLruCache)
LRU(Lest Resently Used)算法,在内存缓存和磁盘缓存中均有用得到,笔者写过一篇Kotlin
版本的LruCache
的实现,感兴趣的可以查看。Kotlin LruCache
缓存大致分为两大部分,内存缓存与磁盘缓存,而内存缓存又包含正在激活使用的弱引用缓存与LruCache。故为三级缓存。
内存内存缓存默认开启,如需关闭则进行如下调用。
Glide.with(this)
.load(url)
//关闭内存缓存
.skipMemoryCache(true)
.into(iv)
在图片加载过程中,会进去到Engine#load
方法中,下面放上部分源代码:
public <R> LoadStatus load(...){
...
//获取缓存图片的key
EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
resourceClass, transcodeClass, options);
//从弱引用缓存中获取,若获取成功则返回并调用onResourceReady进行成功回调
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active, DataSource.MEMORY_CACHE);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
//从内存缓存LruCache中获取,若成功获取则返回并调用onResourceReady进行成功回调
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
//若上方的缓存没用命中,则构建EngineJob,随后会进行磁盘缓存获取、网络请求
...
}
上方总的流程是首先从弱引用缓存中取,再去从内存中去取。
首先分析一下弱引用缓存
private EngineResource<?> loadFromActiveResources(Key key, boolean isMemoryCacheable) {
if (!isMemoryCacheable) {
return null;
}
//从ActiveResources中获取资源
EngineResource<?> active = activeResources.get(key);
if (active != null) {
//当前资源被引用了 +1
active.acquire();
}
return active;
}
final class ActiveResources {
//HashMap 中 储存了弱引用资源
final Map<Key, ResourceWeakReference> activeEngineResources = new HashMap<>();
}
内存缓存LruCache
private EngineResource<?> loadFromCache(Key key, boolean isMemoryCacheable) {
if (!isMemoryCacheable) {
return null;
}
//内部调用remove方法,返回当前资源并且将其从内存LruCache中移除
EngineResource<?> cached = getEngineResourceFromCache(key);
if (cached != null) {
//资源被引用+1
cached.acquire();
//将当前资源加入到 弱引用集合
activeResources.activate(key, cached);
}
return cached;
}
上方的注释很明确了,但是我们发现,内存的二级缓存中存在着交互,比如说,如果从内存LruCache中找到资源后,内存中就将该资源移除了,转而加入到弱引用集合中了。
那么上面还有一个资源引用数+1是干什么的呢?
它主要统计当前资源被多少个地方引用/使用(一张图片被多个地方展示),其中被引用一次就+1,这时候资源肯定都在弱引用集合,如果不引用资源了就-1,直到引用数为0,就将资源从弱引用集合存入到内存LruCache。
总的来说,弱引用集合存的是当前正在使用的资源(若不使用,随时被系统回收),重复利用;内存LruCache,存的则是,之前使用过但当前不再使用过的资源。二者之间存在交互。
而整体内存缓存主要的作为即为防止同一张图片(包括尺寸大小都一样)的资源,被重复加入内存,同时提高相应速度。
磁盘磁盘缓存有存在以下五种策略:默认为AUTOMATIC
- ALL 远程图片资源使用 DATA 和 RESOURCE 缓存,本地图片只使用 RESOURCE 缓存;
- NONE 不缓存任何图片资源;
- DATA 将检索到的原始图片资源(解码之前的)写入磁盘缓存;
- RESOURCE 将检索到的原始图片资源解码之后(压缩或转换)再写入磁盘缓存;
- AUTOMATIC 尝试根据数据源智能选择策略,数据源可以是:DataFetcher、EncodeStrategy、ResourceEncoder;
使用diskCacheStrategy
可以调整缓存策略,比如:
Glide.with(this)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(iv);
若上方内存二级缓存没用命中,则会执行到接下来的流程DecodeJob#onDataFetcherReady
,
@Override
public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher,
DataSource dataSource, Key attemptedKey) {
...
try {
//会从磁盘获取数据
decodeFromRetrievedData();
} finally {
GlideTrace.endSection();
}
}
}
总结
三级缓存读取顺序为:弱引用缓存 -> LruCache -> DiskLruCache。
创作不易,如有帮助一键三连咯🙆♀️。欢迎技术探讨噢!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)