Glide双内存缓存加载机制详细介绍
Glide作为Android主流图片加载库,其高效的内存缓存机制是核心优势之一,主要分为“活动资源缓存”(Active Resources)和“内存LRU缓存”(Memory Cache)两级。这两级缓存协同工作,共同优化图片加载性能与内存利用率。以下从工作原理、实现方式及核心差异三方面深入解析:
一、活动资源缓存(Active Resources)
1. 定位与作用
- 核心目标:保护当前正在展示的图片资源不被回收,避免因内存压力导致已显示图片被意外销毁。
- 适用场景:图片正在被
ImageView
或其他组件使用(例如界面可见时)。 - 生命周期绑定:与页面生命周期同步,当页面销毁时,缓存自动释放
。
2. 技术实现
- 数据结构:使用
HashMap<Key, ResourceWeakReference>
存储资源,其中ResourceWeakReference
是弱引用(WeakReference
)的子类,指向图片资源对象
。
- 引用管理:
- 弱引用确保资源未被强引用持有时可被GC回收。
- 配合
ReferenceQueue
监听回收事件,自动清理无效缓存项
。
- 引用计数:
- 同一资源被多个
ImageView
使用时,引用计数递增。 - 当引用归零时,资源从活动缓存移除并转移到内存LRU缓存
- 同一资源被多个
。
3. 工作流程
// 资源被使用时加入活动缓存
activeResources.activate(key, resource);
// 资源释放时移出
activeResources.deactivate(key);
二、内存LRU缓存(Memory Cache)
1. 定位与作用
- 核心目标:缓存最近使用但当前未被展示的图片,减少重复解码开销。
- 适用场景:图片已加载过但当前未被界面使用(例如页面切换后仍保留)。
- 缓存策略:采用LRU(最近最少使用)算法管理缓存空间
。
2. 技术实现
- 数据结构:
LruResourceCache
继承自Android的LruCache
,底层依赖LinkedHashMap
(按访问顺序排序)
。
- 缓存回收:
- 当缓存满时,自动淘汰最久未使用的资源。
- 支持动态调整大小(如根据设备内存比例分配)
。
- 资源释放:
- 被移除的资源可能加入
BitmapPool
(位图复用池),而非直接销毁
- 被移除的资源可能加入
。
3. 工作流程
// 从内存缓存获取资源
Resource<?> cached = memoryCache.get(key);
// 资源加入缓存
memoryCache.put(key, resource);
三、两级缓存的核心区别
特性 | 活动资源缓存 (Active Resources) | 内存LRU缓存 (Memory Cache) |
存储资源状态 | 正在使用中 | 近期使用过但当前未使用 |
数据结构 |
|
|
引用类型 | 弱引用(依赖引用计数) | 强引用(LRU管理) |
回收触发条件 | 资源引用计数归零 | 缓存空间不足或系统内存压力 |
性能优先级 | 最高(加载时优先检查) | 次高(活动缓存未命中时检查) |
生命周期关联 | 与页面生命周期同步 | 与应用进程生命周期同步 |
是否主动清理 | 是(页面销毁时自动释放) | 是(LRU淘汰或 |
四、实际应用与优化建议
- 避免内存泄漏
Glide通过绑定页面生命周期自动释放活动缓存,开发者需确保传入Context
为Activity/Fragment
而非ApplicationContext
。
- 缓存策略调优
- 禁用内存缓存(特殊场景,比如需要下载图片时):
.skipMemoryCache(true)
- 动态调整缓存大小(适配不同设备):
- GlideBuilder
();
- GlideBuilder
builder.setMemoryCache(new DynamicLruCache(context));
// 根据设备内存动态计算
- 复用Bitmap内存
资源从内存LRU缓存移除后可能进入BitmapPool
,供后续解码复用,减少内存碎片与GC频率
。
总结
Glide的双层内存缓存设计兼顾了资源保护(活动缓存)与历史复用(LRU缓存),通过弱引用+LRU+引用计数的组合,在避免OOM的同时最大化缓存命中率。理解其差异有助于开发者针对性能瓶颈(如列表快速滑动时的卡顿)定向优化,例如调整缓存比例或预加载策略