牛马拉磨的公司是一个直播项目,后台队友反馈说某些图片资源(头像),资源调用很大...我就纳闷了,已经用Glide和Coil等开源库做多级缓存了,理论上不应该出现重复调用呀.
所以一键三连,做过了,没办法,重启试试???
Waht...不对...重启,这貌似就是移动端调用的问题.
问题流程:
Glide/Coil 加载大量图片后--->缓存不生效--->请求网络资源重新下载.
说明:
也就是说加载框架的缓存达到了临界值,为了加载新的资源清理了旧的资源为新资源腾空空间,导致其他用到旧的资源的地方需要重新加载(直播间,礼物聊天室,以及原先缓存的封面叠加)
1: 原先的Glide源码分析以及问题梳理
2: 三级缓存,LruCache,DiskLruCache重要概念
图片资源三级缓存说明

LruCache(内存缓存):一种基于 最近最少使用(LRU)算法 的内存缓存,用于快速存储和访问对象,存放在 RAM 中,进程结束后数据会丢失。
重点:超内存 → 直接删最久未用条目。
DiskLruCache(磁盘缓存) :一种基于 LRU 算法 的磁盘缓存,将对象以文件形式存储在磁盘上,支持较大容量,重启应用后仍可访问。
重点:超磁盘 → journal 找最久未用条目 → 删除对应文件。
3:问题梳理
Glide/Coil-->加载图片-->内存不存在-->加载磁盘(已达到临界值)-->开启下载网络资源-->磁盘运行时内存-->展示
因为磁盘空间已达到临界值,磁盘依据DiskLruCache算法清理了磁盘,为新资源腾空空间.
问题重现:
整个App共用了一个Glide和Coil的磁盘缓存,当大量资源(头像,封面,礼物等),占用了磁盘缓存,当直播间加载新的资源后导致磁盘缓存已经满了,就会陷入清理下载再清理再下载的循环怪圈.
简单比喻:
现在你把 全家人的冰箱都放在一个小柜子里,冰箱满了,拿东西时总是把你刚放的东西挤掉 → 永远吃不到新鲜食物。
磁盘缓存"循环挤占"问题,本质原因是:
-
全局共用磁盘缓存
Glide / Coil 默认都是整个 App 公用一个 DiskCache。
所有模块(头像、封面、礼物、直播资源)都写进同一个缓存目录。
-
缓存容量有限
当直播间大量资源(大图、频繁更新)写入时,会触发 DiskLruCache 清理 。
清理会删除 最久未使用 的文件,但在高频访问场景下,你想保留的"近期资源"也可能被误删,尤其是大资源占满空间时。
-
下载-清理-再下载循环
典型链路:
markdown新资源下载 ↓ 缓存满 → DiskLruCache 清理最久未用文件 ↓ 被删掉的资源又被需要 → 重新下载 ↓ 下载后再清理 → 无限循环这就是你说的 "循环怪圈"。
4:解决方案
App图片资源缓存,区分存储类型就可以了.日常的资源就执行,框架的缓存.特殊资源(礼物,头像),高频资源分开单独存储和加载.
-
永久资源存储

-
永久资源获取

总结
问题原因:
整个App用一个磁盘缓存池,导致缓存池满了,清理缓存,在高频加载的情况下导致资源频繁加载网络头像
问题处理:
多个磁盘缓存池缓存不同的资源
后续功能:
- 缓存优先级 对不常用的大图,可以考虑 不写入磁盘缓存 或 写入单独目录。
- 定时清理 后台定时清理
- 缓存时效 对图片增加时效 后台清理超时的资源