Glide内存缓存的读取与写入

Android框架源码分析——Glide缓存机制源码分析 1、Glide的缓存 Glide 在加载图片时会依次访问以下缓存: 活动资源 (Active Resources) - 现在是否有另一个 View 正在展示这张图片? 内存缓存 (Memory cache) - 该图片是否最近被加载过并仍存在于内存中? 资源类型(Resource) - 该图片是否之前曾被解码、转换并写入过磁盘缓存? 数据来源 (Data) - 构建这个图片的资源是否之前曾被... 阅读详情

简单描述:
Glide缓存读取的顺序是:Lru算法缓存、弱引用缓存、磁盘缓存
Glide缓存写入的顺序是:弱引用缓存、Lru算法缓存、磁盘缓存(不准确)

下面叙述一下三级缓存的流程:
当我们的APP中想要加载某张图片时,先去LruCache中寻找图片,如果LruCache中有,则直接取出来使用,如果LruCache中没有,则去WeakReference中寻找,如果WeakReference中有,则从WeakReference中取出图片使用,同时将图片重新放回到LruCache中,如果WeakReference中也没有图片,则去文件系统中寻找,如果有则取出来使用,同时将图片添加到LruCache中,如果没有,则连接网络从网上下载图片。图片下载完成后,将图片保存到文件系统中,然后放到LruCache中。

严格来讲,并没有什么Glide的三级缓存,因为Glide的缓存只有两个模块,一个是内存缓存,一个是磁盘缓存。其中内存缓存又分为Lru算法的缓存和弱引用缓存。

LruCache算法,Least Recently Used,又称为近期最少使用算法。主要算法原理就是把最近所使用的对象的强引用存储在LinkedHashMap上,并且,把最近最少使用的对象在缓存池达到预设值之前从内存中移除。

public class LruCache<T, Y> {
    private final LinkedHashMap<T, Y> cache = new LinkedHashMap<T, Y>(100, 0.75f, true);
}

弱引用缓存:

public class Engine implements EngineJobListener,
        MemoryCache.ResourceRemovedListener,
        EngineResource.ResourceListener {
    //弱引用缓存
    private final Map<Key, WeakReference<EngineResource<?>>> activeResources;
    ...
    activeResources = new HashMap<Key, WeakReference<EngineResource<?>>>();
}

我们先来看缓存读取:Lru算法缓存、弱引用缓存、磁盘缓存
首先 memoryCache的初始值是一个LruResourceCache对象,即默认是lru算法的缓存

GlideBuilder.java
	private MemoryCache memoryCache;
    Glide  createGlide() {
		memoryCache = new LruResourceCache(calculator.getMemoryCacheSize());
    }
 
Engine.java
	private final MemoryCache cache;
	public <T, Z, R> LoadStatus load(...){
		...
		//获取Lru算法的缓存,如果没有,就从弱引用中获取缓存
		EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
		...
		//从弱引用中获取缓存
		EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
		...
		//从磁盘中获取缓存
		EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);
        DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, 
               fetcher, loadProvider, transformation,transcoder,             
               diskCacheProvider, diskCacheStrategy, priority);
	}

接下来我们看缓存写入:弱引用缓存、Lru算法缓存、磁盘缓存
内存缓存的写入:
EngineResource是用一个acquired(int)变量用来记录图片被引用的次数,调用acquire()方法会让变量加1,
调用release()方法会让变量减1。
acquired变量大于0的时候,说明图片正在使用中,也就应该放到activeResources弱引用缓存当中;
如果acquired变量等于0了,说明图片已经不再被使用了,那么此时会调用方法来释放资源,
这里首先会将缓存图片从activeResources中移除,然后再将它put到LruResourceCache当中。
这样也就实现了正在使用中的图片使用弱引用来进行缓存,不在使用中的图片使用LruCache来进行缓存的功能。

public class Engine implements EngineJobListener,
        MemoryCache.ResourceRemovedListener,
        EngineResource.ResourceListener {
    ...    
 
    @Override
    public void onEngineJobComplete(Key key, EngineResource<?> resource) {
        Util.assertMainThread();
        // A null resource indicates that the load failed, usually due to an exception.
        if (resource != null) {
            resource.setResourceListener(key, this);
            if (resource.isCacheable()) {
                activeResources.put(key, new ResourceWeakReference(key, resource, getReferenceQueue()));
            }
        }
        jobs.remove(key);
    }
 
    ...
}

现在就非常明显了,可以看到,在第13行,回调过来的EngineResource被put到了activeResources当中,也就是在这里写入的缓存。

那么这只是弱引用缓存,还有另外一种LruCache缓存是在哪里写入的呢?这就要介绍一下EngineResource中的一个引用机制了。观察刚才的handleResultOnMainThread()方法,在第15行和第19行有调用EngineResource的acquire()方法,在第23行有调用它的release()方法。其实,EngineResource是用一个acquired变量用来记录图片被引用的次数,调用acquire()方法会让变量加1,调用release()方法会让变量减1,代码如下所示:

class EngineResource<Z> implements Resource<Z> {
 
    private int acquired;
    ...
 
    void acquire() {
        if (isRecycled) {
            throw new IllegalStateException("Cannot acquire a recycled resource");
        }
        if (!Looper.getMainLooper().equals(Looper.myLooper())) {
            throw new IllegalThreadStateException("Must call acquire on the main thread");
        }
        ++acquired;
    }
 
    void release() {
        if (acquired <= 0) {
            throw new IllegalStateException("Cannot release a recycled or not yet acquired resource");
        }
        if (!Looper.getMainLooper().equals(Looper.myLooper())) {
            throw new IllegalThreadStateException("Must call release on the main thread");
        }
        if (--acquired == 0) {
            listener.onResourceReleased(key, this);
        }
    }
}

也就是说,当acquired变量大于0的时候,说明图片正在使用中,也就应该放到activeResources弱引用缓存当中。而经过release()之后,如果acquired变量等于0了,说明图片已经不再被使用了,那么此时会在第24行调用listener的onResourceReleased()方法来释放资源,这个listener就是Engine对象,我们来看下它的onResourceReleased()方法:

public class Engine implements EngineJobListener,
        MemoryCache.ResourceRemovedListener,
        EngineResource.ResourceListener {
 
    private final MemoryCache cache;
    private final Map<Key, WeakReference<EngineResource<?>>> activeResources;
    ...    
 
    @Override
    public void onResourceReleased(Key cacheKey, EngineResource resource) {
        Util.assertMainThread();
        activeResources.remove(cacheKey);
        if (resource.isCacheable()) {
            cache.put(cacheKey, resource);
        } else {
            resourceRecycler.recycle(resource);
        }
    }
 
    ...
}

可以看到,这里首先会将缓存图片从activeResources中移除,然后再将它put到LruResourceCache当中。这样也就实现了正在使用中的图片使用弱引用来进行缓存,不在使用中的图片使用LruCache来进行缓存的功能。
这就是Glide内存缓存的实现原理。

来自:https://www.yuque.com/u435816/omigec/ecd40w

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。

相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

全套视频资料:
一、面试合集

二、源码解析合集

三、开源框架合集

欢迎大家一键三连支持,若需要文中资料,直接点击文末优快云官方认证微信卡片免费领取

安卓Glide那些事情面试,一篇全部搞定 1、优先从活动缓存获取2、活动缓存没有就再内存缓存中寻找3、内存缓存没有,就去磁盘缓存读取4、磁盘缓存没有就去网络获取本地文件读取。 阅读详情

相关推荐

Android 高频面试题解析:Glide流程解析

Glide是一款流行的图片加载库,它提供了丰富的功能和扩展接口,可以很好地实现图片的加载和显示。本文将对Glide的流程进行解析,从初始化入口开始,一步一步深入源码,讲解Glide的实现原理和代码细节。同时,还将介绍如何自定义加载策略等。

工宗浩生财指南针 2204

Glide原理及面试

1.怎么在项目中加载图片的? 用Glide比较多,Glide里的ImageLoader解决图片错乱,还有图片缓存,节约内存空间 2.Glide哪些好处? 可以播放gif图 图片有序位置有序排放 因为:图片标志缓存绑定,只展示绑定的图片地址,不是乱显示,防止图片位置错乱。 比其它图片框架优秀 缺点:会出问题,应该从0秒开始3秒结束,结果每次播放git图片都是从1秒或者2秒,或者0.8秒开始,播放太快,给用户体验效果差 3.Glide好处体现在哪? 其它图片不支持gif图片播放,只有Glide框架,因为它可

weixin_50005657的博客 1818

字节Android岗面试必问:Glide的缓存机制,金三银四旗开得胜

} if (decodeFormat == null) { decodeFormat = DecodeFormat.DEFAULT; } return new Glide(engine, memoryCache, bitmapPool, context, decodeFormat); } } 这里也就是构建Glide对象的地方了。那么观察第22行,你会发现这里new出了一个LruResourceCache,并把它赋值到了memoryCache这个对象上面...

m0_61417997的博客 976

Android面试总结之Glide源码级理解

解答:通过枚举,可以自定义Glide的缓存行为:缓存原始图片和转换后的图片到磁盘缓存。不使用磁盘缓存。只缓存转换后的图片到磁盘缓存。只缓存原始图片到磁盘缓存。

2301_80329517的博客 1879

Glide 4.12图片框架之多级缓存源码设计分析

一、Glide缓存初识 在上两篇文章中,我们从源码角度分析Glide框架加载图片的流程、以及Glide图片通过巧妙的空view的Fragment的设计实现的Glide的图片加载的三大生命周期函数onStart、onStop、onDestroy。Glide的框架的源码量确实比较大,今天我们再详细分析一下,Glide的框架的缓存模块的设计。 默认情况下,Glide 会在开始一个新的图片请求之前检查以下多级的缓存: 活动资源 (Active Resources) - 现在是否有另一个 View 正在展示这张图片

HYM BLOG 1228

Glide缓存机制

Glide缓存机制 Glide缓存非常先进,很灵活,很全面,总体上来讲有内存缓存和磁盘文件缓存。缓冲机制概括来讲就是读缓存以及是写入缓存的机制。而Glide读缓存时机就是先内存缓存查找再到磁盘缓存查找最后网络,写入缓存则就是在获取到原始source图片之后,先写入磁盘缓存,再加入内存缓存。 每个缓存查找都是通过key来查询,一般都是直接用下载url来作为key,那Glide的key呢。直接看下

在路上-codingAndlearning 9345

一篇文章搞定《图片框架Glide的三级缓存(全)》

首先三级缓存是Glide中非常重要的缓存机制,也是这种缓存机制才让我们的图片加载的效率,性能如此的高。下面我们来看看具体的三级缓存内容我们从三级缓存读取的源头、到三级缓存的获取、到三级缓存的写入都分析了。

小孟来码的博客 4992

从零构建:Trinamic API在STM32上的深度移植与TMC-IDE通信实战

本文详细介绍了如何从零开始在STM32平台上深度移植Trinamic API,并实现与TMC-IDE工具的稳定通信。内容涵盖SPI底层驱动定制、寄存器配置、高级功能实现及调试技巧,重点解析了TMC5160芯片的集成实践,帮助开发者构建可靠的嵌入式运动控制系统。

w1x2y3的博客 254

Glide——缓存分析整理

文章目录LruCache概述原理DiskLruCache概述Glide缓存概述资源分类缓存设计Glide 缓存源码分析1、生成key2、创建缓存对象LruResourceCache3、获取内存缓存中的图片4、开启加载图片线程5、获取磁盘缓存6、写入磁盘7、写入内存缓存写入弱引用缓存写入LruCache LruCache 概述 LruCache是Android 3.1所提供的一个缓存类,所以在And...

PdKingLiu 2051

Multisim实战:从8选1到32选1数据选择器的完整搭建指南(附常见问题解决)

本文提供了一份详尽的Multisim实战指南,手把手教你从基础的8选1数据选择器开始,逐步级联搭建16选1乃至32选1数据选择器。文章深入剖析了级联的核心逻辑、片选方案以及使用译码器的专业方法,并附带了电源连接、输出冲突、信号毛刺等常见问题的诊断与解决技巧,帮助电子工程学生和爱好者扎实掌握数字电路的系统设计与仿真调试。

dd012的博客 731

PCB数据集

整理了一部分PCB数据集

m0_57996537的博客 3867

Android图片加载框架最全解析(三),深入探究Glide的缓存机制

可以看到,只需要调用skipMemoryCache()方法并传入true,就表示禁用掉Glide的内存缓存功能。没错,关于Glide内存缓存的用法就只有这么多,可以说是相当简单。但是我们不可能只停留在这么简单的层面上,接下来就让我们就通过阅读源码来分析一下Glide的内存缓存功能是如何实现的。其实说到内存缓存的实现,非常容易就让人想到LruCache算法(Least Recently Used),也叫近期最少使用算法。它的主要算法原理就是把最近使用的对象用强引用存储在LinkedHashMap中,并且把最近

2401_84149836的博客 600

MediaCodec视频解码流程详解及参考demo

本文主要讲解mediacodec的视频解码流程,及demo参考例子。

分享音视频技术 7877

Glide从磁盘加载图片资源的流程

Glide 从磁盘中加载图片的过程。涉及到如何从网络加载图片,和写入 DATA 磁盘缓存、RESOURCE 磁盘缓存、ActiveResources 缓存的时机,以及如何从 ModelLoaderRegistry 中获取 ModelLoader。

哈罗德Android笔记 861

新能源汽车电池及充电原理详解

本文详细介绍了新能源汽车的电池包结构、铅酸电池充放电原理,以及交流和直流充电的工作原理和优缺点。内容涵盖电池串联并联原因、充电设备如车载充电机、交流充电桩和直流充电桩的介绍,以及不同充电模式的连接方式。通过对充电过程的深入探讨,有助于读者理解新能源汽车的充电技术。

让你爱上电路设计 4528

一个中科大差生的8年程序员工作总结

今年终于从大菊花厂离职了,离职前收入大概60w不到吧,在某乎属于比较差的,今天终于有空写一下自己的职场故事,也算是给自己近8年的程序员工作做个总结复盘。近8年有些事情做对了,也有更多事情做错了,在这里记录一下,希望能够给后人一些帮助吧,也欢迎私信交流。文笔不好,见谅,有些细节记不清了,如果有出入,就当是我编的这个故事吧。 PS:有几个问题先在这里解释一下,评论就不一一回复了 1、关于差生,我本人在科大时确实成绩偏下,差生主要讲这一点,没其他意思。 2、因为买房是我人生中的大事,我认为需要记录和总结一下

陈小房的自我修炼 5万+

字节Android岗面试必问:Glide的缓存机制(2)

今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。还有。

2401_83621918的博客 745

我用C#实现上位机数据一键导出Excel:从乱码到百万行数据秒级导出的实战技巧

ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("日报表");// 1. 标题(合并单元格)worksheet.Cells["A1"].Value = $"产线日报表 -DateTimeNowToString// 2. 表头和数据(同上)worksheet.Cells["A3"].Value = "时间";// ...省略表头和数据填充// 3. 合计行(公式计算)

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 712

Glide源码解析---缓存篇

Glide的缓存分为两部分 内存缓存 硬盘缓存 今天我们从源码的角度来分析。 Glide.with(context).load(url).into(imageView); 上面一行代码我们就可以实现图片的加载,这一行代码背后进行了成吨的工作,我们今天只来看看它关于缓存的部分。 Engine load() public &amp;amp;amp;amp;lt;T, Z, R&amp;amp;amp;amp;gt; LoadStatus load(Key s...

omyrobin的专栏 293

Codex 的 AGENTS.md 到底怎么写?前端、后端两套实战模板,照抄就能用

文件名是大写AGENTS.md,放在项目根目录构建、测试、类型检查命令都是可直接复制执行的只写了 Agent 从代码里推断不出来的约定红线规则用了明确的否定句式(禁止/不要/Never)标注了自动生成目录和禁止修改的模块写清了交付要求(改动清单 + 验证命令 + 风险说明)没有任何密钥、密码、连接串整体一页能看完,核心要点 10 条以内每一条都能通过"删掉会不会更容易犯错"的测试一份短小精准的 AGENTS.md,比一份充斥模糊规则的长文件有用得多。

篮球界最会写bug的人;程序猿中打球最菜的人。 615

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Glide框架解析

load方法最终做的就是进行一些初始化的操作,获得了一个DrawableTypeRequest对象,通过这个对象我们就可以获得图片请求的request,然后再接下来的into方法中使用。得到ImageViewTarget 显示图片的地方// 得到ImageViewTarget 显示图片的地方构建一个请求一般的图片加载库,都是通过内存缓存LruCache、磁盘缓存DiskLruCache中去拿数据,那么Glide也是这样么?Glide的缓存设计可以说是非常先进的,考虑的场景也很周全。

2301_82244623的博客 1019

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

glide-源码解析-2

glide-源码解析-2

dbs1215的专栏 757

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

android glide网络缓存,Android 【手撕Glide】--Glide缓存机制(面试)

本文源码解析基于Glide 4.6.1引入缓存的目的1、减少流量消耗,加快响应速度;2、Bitmap 的创建/销毁比较耗内存,可能会导致频繁GC;使用缓存可以更加高效地加载 Bitmap,减少卡顿。Glide缓存流程Glide缓存分为内存缓存和磁盘缓存,其中内存缓存是由弱引用+LruCache组成。取的顺序是:弱引用、LruCache、磁盘存的顺序是:磁盘、弱引用、LruCache这张亲手制作的图...

weixin_33492955的博客 407

2024年Android最全字节Android岗面试必问:Glide的缓存机制,字节跳动历年Android中高级面试题全收录

(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总)面试成功其实是必然的,因为我做足了充分的准备工作,包括刷题啊,看一些Android核心的知识点,看一些面试的博客吸取大家面试的一些经验,

2301_82242990的博客 846
上一篇: 在Android面试前背八股和学面试技巧真的有用吗?
下一篇: 推特证明求职的尽头是被裁?Android工程师们小心了
不秃头de程序猿
博客等级 码龄5年 4089粉丝 1478原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值