Glide Bitmap复用笔记

23 阅读3分钟

Glide复用Bitmap的核心是通过一个名为 BitmapPool 的“回收池”来管理Bitmap对象的。它的目标非常明确:避免频繁创建和销毁Bitmap,从而减少内存分配开销、降低垃圾回收(GC)频率,在图片列表快速滑动等场景下能显著提升流畅度并降低OOM风险。

为了让你快速理解,下面这张表概括了Bitmap复用的完整工作流程:

阶段关键动作说明
1. 请求获取解码器向BitmapPool申请需要解码图片时,会携带目标宽、高、格式(如ARGB_8888)向池子申请。
2. 查找匹配执行匹配策略池子优先返回尺寸、格式完全相同的Bitmap;如果没有,则可能返回一个尺寸更大的(例如,不超过所需尺寸的8倍)进行复用。
3. 解码填充使用inBitmap将匹配到的Bitmap通过BitmapFactory.Options.inBitmap设置,新图片的数据会直接解码填充到这个“旧壳子”里,避免了新建对象。
4. 使用与释放放回池中当这张图片不再显示(例如ImageView被回收),其Bitmap会被放回BitmapPool,而不是立即被GC回收,等待下一次复用。

🧩 技术原理:BitmapPool如何工作

BitmapPool的核心实现类是LruBitmapPool,它内部通过几个关键组件协同工作。

  • LruBitmapPool:这是管理池的“管家”。它设定了池子的总内存上限(maxSize),并采用LRU(最近最少使用)算法进行管理。当池子满了或有新的Bitmap要放入时,它会驱逐最久未被使用的Bitmap。
  • SizeConfigStrategy(策略):这是负责查找和匹配Bitmap的“智能引擎”。它根据Bitmap的尺寸(size)和配置格式(config)进行分组和索引。其“模糊匹配”机制允许复用尺寸稍大的Bitmap(在一定倍数内),这大大提高了复用成功率。
  • GroupedLinkedMap(存储):这是实际存储Bitmap对象的“仓库”。它以链表形式组织,便于实现LRU逻辑,快速移除最旧的或添加最新的Bitmap。

整个机制建立在Android系统提供的 inBitmap API之上。从Android 4.4(API 19)开始,该系统支持复用尺寸不同的Bitmap,这正是Glide能高效复用的基础。

💡 实践价值与注意事项

理解这个机制后,你可以更好地利用和优化它:

  • 主要价值:直接减少了列表滑动等场景下的内存抖动(频繁GC导致的卡顿),并整体降低了内存峰值,提升了应用稳定性。
  • 复用条件:并非所有Bitmap都能被复用。主要条件是Bitmap必须是可变的isMutable() == true),并且其内存大小不超过池子的最大限制。
  • 配置调整:虽然Glide有智能的默认配置,但在特定场景下(如需要处理大量超大图片的应用),你可以通过自定义AppGlideModule来调整BitmapPool的大小,以平衡复用率和内存占用。

如果你想进一步了解如何在代码中自定义BitmapPool的大小,或者想看看在特定场景(如低内存设备)下的优化配置示例,我可以为你提供更详细的介绍。