当前位置:网站首页>Glide缓存核心原理详解
Glide缓存核心原理详解
2022-08-10 22:13:00 【AD钙奶-lalala】
Glide目前几乎是Android图片框架的不二选择,那么你知道Glide有哪些优点吗?
- 使用简单,链式调用( Glide.with(context).load(url).into(iv) )
- 占用内存较小,默认使用RGB_565,相比较Picasso内存减少一半(RGB_8888)
- 与activity生命周期绑定,避免内存泄漏
- 缓存优化
今天的主题是一起来研究一下Glide的核心原理。
Glide的三级缓存原理是什么?
读取一张图片的顺序:LRU算法缓存->弱引用缓存->磁盘缓存(如果设置了的话)。
我们的APP中想要加载某张图片时,先去LruCache中寻找图片,如果LruCache中有,则直接取出来使用,并将该图片放入WeakReference中,如果LruCache中没有,则去WeakReference中寻找,如果WeakReference中有,则从WeakReference中取出图片使用,如果WeakReference中也没有图片,则从磁盘缓存/网络中加载图片。
注:图片正在使用时存在于 activeResources 弱引用map中。
缓存图片的写入顺序:弱引用缓存->LRU算法缓存->磁盘缓存。
当图片不存在的时候,先从网络下载图片,然后将图片存入弱引用中,glide会采用一个acquired(int)变量用来记录图片被引用的次数,当acquired变量大于0的时候,说明图片正在使用中,也就是将图片放到弱引用缓存当中;如果acquired变量等于0了,说明图片已经不再被使用了,那么此时会调用方法来释放资源,首先会将缓存图片从弱引用中移除,然后再将它put到LruResourceCache当中。这样也就实现了正在使用中的图片使用弱引用来进行缓存,不再使用
中的图片使用LruCache来进行缓存的功能。
关于LRUCache:
最近最少使用算法,设定一个缓存大小,当缓存达到这个大小之后,会将最老的数据移除,避免图片占用内存过大导致OOM。LruCache 内部用LinkHashMap存取数据,在双向链表保证数据新旧顺序的前提下,设置一个最大内存,往里面put数据的时候,当数据达到最大内存的时候,将最老的数据移除掉,保证内存不超过设定的最大值。
关于LinkedHashMap:
LinkHashMap 继承HashMap,在 HashMap的基础上,新增了双向链表结构,每次访问数据的时候,会更新被访问的数据的链表指针,具体就是先在链表中删除该节点,然后添加到链表头header之前,这样就保证了链表头header节点之前的数据都是最近访问的(从链表中删除并不是真的删除数据,只是移动链表指针,数据本身在map中的位置是不变的)。
前面说了一堆,其实重点大家也很明白,就是这个LRUCache:
public class LruCache<T, Y> {
private final LinkedHashMap<T, Y> cache =
new LinkedHashMap<T, Y>(100, 0.75f, true);//最后一个传入true,代表基于顺序访问
private int maxSize;
private final int initialMaxSize;
private int currentSize = 0;
public LruCache(int size) {
this.initialMaxSize = size;
this.maxSize = size;
}
public void setSizeMultiplier(float multiplier) {
if (multiplier < 0) {
throw new IllegalArgumentException("Multiplier must be >= 0");
}
maxSize = Math.round(initialMaxSize * multiplier);
evict();
}
protected int getSize(Y item) {
return 1;
}
protected void onItemEvicted(T key, Y item) {
// optional override
}
public int getMaxSize() {
return maxSize;
}
public int getCurrentSize() {
return currentSize;
}
public boolean contains(T key) {
return cache.containsKey(key);
}
public Y get(T key) {
return cache.get(key);
}
public Y put(T key, Y item) {
final int itemSize = getSize(item);
if (itemSize >= maxSize) {
onItemEvicted(key, item);
return null;
}
final Y result = cache.put(key, item);
if (item != null) {
currentSize += getSize(item);
}
if (result != null) {
// TODO: should we call onItemEvicted here?
currentSize -= getSize(result);
}
evict();
return result;
}
public Y remove(T key) {
final Y value = cache.remove(key);
if (value != null) {
currentSize -= getSize(value);
}
return value;
}
public void clearMemory() {
trimToSize(0);
}
protected void trimToSize(int size) {
Map.Entry<T, Y> last;
while (currentSize > size) {
last = cache.entrySet().iterator().next();//基于顺序访问
final Y toRemove = last.getValue();
currentSize -= getSize(toRemove);
final T key = last.getKey();
cache.remove(key);
onItemEvicted(key, toRemove);
}
}
private void evict() {
trimToSize(maxSize);
}
}
解释一下一个重要的成员变量maxSize是什么意思:资源的最大字节数。
我们先来分析一下put方法:
- 首先获取资源的字节数itemSize
- 如果itemSize直接超限制,返回,onItemEvicted方法在子类有实现,后面再看
- cache.put将资源加到LinkedHashMap里面
- item != null 将item的size加到currentSize上
- result != null 说明缓存已存在,前面加到currentSize里面去的要再去掉
- 最后调用evict方法
再来分析一下evict(意思是逐出)方法:
- 调用trimToSize
- 遍历获取最后一个资源,移出cache
我们再来看下LRUCache的子类来加深我们的理解:
public class LruResourceCache extends LruCache<Key, Resource<?>>
implements MemoryCache {
private ResourceRemovedListener listener;
/**
* Constructor for LruResourceCache.
*
* @param size The maximum size in bytes the in memory cache can use.
*/
public LruResourceCache(int size) {
super(size);
}
@Override
public void setResourceRemovedListener(ResourceRemovedListener listener) {
this.listener = listener;
}
@Override
protected void onItemEvicted(Key key, Resource<?> item) {
if (listener != null) {
listener.onResourceRemoved(item);
}
}
@Override
protected int getSize(Resource<?> item) {
return item.getSize();
}
@SuppressLint("InlinedApi")
@Override
public void trimMemory(int level) {
if (level >= android.content.ComponentCallbacks2.TRIM_MEMORY_MODERATE) {
// Nearing middle of list of cached background apps
// Evict our entire bitmap cache
clearMemory();
} else if (level >= android.content.ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
// Entering list of cached background apps
// Evict oldest half of our bitmap cache
trimToSize(getCurrentSize() / 2);
}
}
}
- getSize是获取资源字节数的意思
- onItemEvicted可以理解为将资源移除
时间有点晚了,后面再用一篇文章来分析一下LinkedHashMap的数据结构,晚安,好梦!
边栏推荐
- 《DevOps围炉夜话》- Pilot - CNCF开源DevOps项目DevStream简介 - feat. PMC成员胡涛
- Introduction to the use of counter instructions in Rockwell AB PLC RSLogix5000
- shell编程之免交互
- 美味的佳肴
- OneNote tutorial, how to organize notebooks in OneNote?
- 合并k个已排序的链表
- Spark基础【RDD转换算子】
- B站数据分析岗实习生面试记录
- CIKM2022 | 基于双向Transformers对比学习的序列推荐
- camera预览流程 --- 从HAL到OEM
猜你喜欢
阿里云贾朝辉:云XR平台支持彼真科技呈现国风科幻虚拟演唱会
BM13 determines whether a linked list is a palindrome
LeetCode Daily 2 Questions 02: Reverse the words in a string (1200 each)
Introduction to the use of counter instructions in Rockwell AB PLC RSLogix5000
3598. 二叉树遍历(华中科技大学考研机试题)
68:第六章:开发文章服务:1:内容梳理;article表介绍;创建【article】文章服务;
高数_复习_第5章:多元函数微分学
How does the Weiluntong touch screen display the current value of abnormal data while alarming?
解码2022中国网安强星丨正向建、反向查,华为构建数字化时代的网络安全防线
留言有奖|OpenBMB x 清华大学NLP:大模型公开课更新完结!
随机推荐
【开源教程5】疯壳·开源编队无人机-飞控固件烧写
IM 即时通讯开发如何设计图片文件的服务端存储架构
68: Chapter 6: Develop article services: 1: Content sorting; article table introduction; creating [article] article services;
[Maui official version] Create a cross-platform Maui program, as well as the implementation and demonstration of dependency injection and MVVM two-way binding
金山云CEO王育林离职:正值冲刺港股之际 雷军曾送金砖
OneNote 教程,如何在 OneNote 中整理笔记本?
Service - DHCP principle and configuration
3598. 二叉树遍历(华中科技大学考研机试题)
今日睡眠质量记录75分
shell脚本
RK3399 platform development series explanation (kernel-driven peripherals) 6.35, IAM20680 gyroscope introduction
BM13 determines whether a linked list is a palindrome
测试4年感觉和1、2年时没什么不同?这和应届生有什么区别?
Pro-test is effective | A method to deal with missing features of risk control data
Black cats take you learn Makefile article 13: a Makefile collection compile problem
2021 IDEA creates web projects
pytorch手撕CNN
pytorch tear CNN
学会开会|成为有连接感组织的重要技能
新一代网络安全防护体系的五个关键特征