glide缓存策略和缓存命中

发布于:2025-08-13 ⋅ 阅读:(16) ⋅ 点赞:(0)

一 缓存策略

1 Glide 的 diskCacheStrategy() 一共有 5 种枚举值(DiskCacheStrategy),每种的作用和区别如下:


1. DiskCacheStrategy.ALL

  • 作用:同时缓存原始图片(原图数据)和经过变换(比如裁剪、缩放)后的图片。
  • 特点:
    • 加载相同 URL 但不同尺寸的图片时会用到原图缓存重新生成,节省网络请求。
    • 占用磁盘空间较大。
  • 使用场景:同一图片需要加载多种尺寸版本时(比如列表缩略图 + 详情页原图)。
  • 示例:
Glide.with(context)
    .load(url)
    .diskCacheStrategy(DiskCacheStrategy.ALL)
    .into(imageView)

2. DiskCacheStrategy.DATA

  • 作用:只缓存原始数据(网络下载的原图文件),不缓存经过变换后的版本。
  • 特点:
    • 如果相同 URL 但不同尺寸的图片会再次加载,需要重新执行变换(裁剪、缩放)。
    • 节省磁盘,但 CPU 会多次参与图片处理。
  • 使用场景:图片需要多次处理或每次显示尺寸不固定,且不介意重新计算。
  • 示例:
Glide.with(context)
    .load(url)
    .diskCacheStrategy(DiskCacheStrategy.DATA)
    .into(imageView)

3. DiskCacheStrategy.RESOURCE

  • 作用:只缓存经过变换处理后的图片,不缓存原始数据。
  • 特点:
    • 每次加载相同尺寸的图片时速度很快。
    • 如果需要加载不同尺寸的图片,就得重新从网络获取。
  • 使用场景:固定尺寸、固定变换的图片(比如头像 100×100)。
  • 示例:
Glide.with(context)
    .load(url)
    .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
    .into(imageView)

4. DiskCacheStrategy.NONE

  • 作用:不缓存任何内容(既不缓存原图,也不缓存变换结果)。
  • 特点:
    • 每次都从源头重新加载(网络、本地、ContentProvider 等)。
    • 网络耗时高,但适合加载经常变化的图片(例如验证码、实时数据图)。
  • 使用场景:动态变化的图片。
  • 示例:
Glide.with(context)
    .load(url)
    .diskCacheStrategy(DiskCacheStrategy.NONE)
    .into(imageView)

5. DiskCacheStrategy.AUTOMATIC(默认值)

  • 作用:根据图片来源和变换自动选择最佳策略。
  • 特点:
    • 网络图片:一般缓存变换后的结果(类似 RESOURCE)。
    • 本地图片(assets、file):可能不缓存(因为本地读速度快)。
    • 大部分情况性能和空间占用平衡。
  • 使用场景:不想自己纠结用哪种策略时,直接用默认。
  • 示例:
Glide.with(context)
    .load(url)
    .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC) // 可省略
    .into(imageView)

常用选择建议

  • 列表/固定尺寸头像等 → RESOURCE(加载快,占空间少)。
  • 同一图片多种尺寸 → ALL(减少网络请求)。
  • 动态图片(验证码/频繁变化) → NONE。
  • 懒得选 → 用默认 AUTOMATIC(Glide 4.x 优化得不错)。

如果在做车机空调App那种大图(2500px 宽背景),
会建议用 DiskCacheStrategy.RESOURCE 来直接缓存裁剪/缩放后的版本,
这样 Fragment 切换时就能秒加载,不会卡顿或闪烁。


2 Glide 缓存策略对比表


Glide diskCacheStrategy() 对比表

策略 是否缓存原图(DATA) 是否缓存变换后(RESOURCE) 优点 缺点 适用场景
ALL 原图 & 各种尺寸都可复用,减少网络请求 占磁盘最多 同一 URL 需要多种尺寸或变换
DATA 原图可复用,多尺寸可重新生成 每次都要重新变换,CPU 占用高 多尺寸、多变换,但磁盘紧张
RESOURCE 固定尺寸加载快,占磁盘少 换尺寸需要重新下载 固定尺寸图片(头像、列表)
NONE 每次都拉取最新 网络 & CPU 占用高 验证码、实时图片
AUTOMATIC(默认) 自动决定 自动决定 性能和空间平衡 不可控(依赖 Glide 判断) 大部分情况直接用它


车机空调大图场景建议

  • 如果背景图尺寸固定 → RESOURCE

    • 直接缓存最终展示尺寸,Fragment 切换秒加载。
  • 如果一个图多种尺寸(比如背景 + 缩略图) → ALL

    • 原图 + 各种变换都能直接复用,避免重复请求和变换。

记忆口诀

  • ALL:全缓存(原图 + 变换)
  • DATA:只原图(省空间但要重算)
  • RESOURCE:只结果(快但不通用)
  • NONE:啥都不留(实时变化)
  • AUTO:交给 Glide(偷懒模式)


二 检查缓存是否命中

Glide 缓存命中检查方案:

  • 日志配置
  • 不同缓存命中标识
  • 手动检查缓存 API(日志不够用时)

1. 开启 Glide 全量调试日志

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        Glide.init(
            this,
            GlideBuilder()
                .setLogLevel(Log.DEBUG) // 输出 DEBUG 级别日志
        )
    }
}

这样 Glide 会在 Logcat 中输出类似:

  • 内存缓存命中
Loaded resource from MEMORY_CACHE
  • 磁盘缓存命中
Loaded resource from DISK_CACHE
  • 网络/本地原始加载(没命中任何缓存)
Loaded resource from DATA

说明:

  • MEMORY_CACHE → 命中内存缓存(速度最快,不走磁盘 IO)
  • DISK_CACHE → 命中磁盘缓存(会解码成 Bitmap)
  • DATA → 没有缓存,直接从网络、本地文件或 ContentProvider 读取

2. 通过 RequestListener 精准判断

有时不想看 Logcat,而是想在代码里记录命中情况,这可以用 RequestListener 判断 DataSource:

Glide.with(context)
    .load(url)
    .listener(object : RequestListener<Drawable> {
        override fun onLoadFailed(
            e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean
        ): Boolean {
            Log.e("GlideCheck", "加载失败: ${e?.message}")
            return false
        }

        override fun onResourceReady(
            resource: Drawable?, model: Any?, target: Target<Drawable>?,
            dataSource: DataSource?, isFirstResource: Boolean
        ): Boolean {
            when (dataSource) {
                DataSource.MEMORY_CACHE -> Log.d("GlideCheck", "内存缓存命中")
                DataSource.DISK_CACHE -> Log.d("GlideCheck", "磁盘缓存命中")
                DataSource.DATA -> Log.d("GlideCheck", "缓存未命中(原始数据加载)")
                DataSource.REMOTE -> Log.d("GlideCheck", "网络加载")
                DataSource.LOCAL -> Log.d("GlideCheck", "本地文件加载")
                else -> Log.d("GlideCheck", "未知数据源")
            }
            return false
        }
    })
    .into(imageView)

这样不看日志也能准确知道缓存命中情况,并且可以在 UI 或调试工具里显示。


3. 手动检查缓存是否存在(不触发加载)

有时想提前判断某个 URL 是否已经在磁盘缓存里,可以用:

fun isImageInCache(context: Context, url: String): Boolean {
    val future = Glide.with(context)
        .downloadOnly()
        .load(url)
        .onlyRetrieveFromCache(true) // 只从缓存取,不走网络
        .submit()

    return try {
        future.get() // 如果能拿到文件,说明有缓存
        true
    } catch (e: Exception) {
        false
    }
}

4. 实战判断逻辑

综合起来,可以这样判断:

  1. 先用 onlyRetrieveFromCache(true) 提前检测是否有磁盘缓存(可做预加载优化判断)。
  2. 加载时用 RequestListener 获取真实加载来源(内存/磁盘/网络)。
  3. 配合 Glide 日志 双重验证。

三 Glide缓存流程图

请添加图片描述

四 总结

  1. 缓存策略有五种:ALL,DATA,RESOURCE,NONE,AUTOMATIC(默认),即原图缓存、转换后缓存,原图缓存,转换后缓存,不缓存,由glide处理缓存策略。
  2. 缓存命中,可以通过日志查看,RequestListener 和onlyRetrieveFromCache(true) 来查看是否命中了缓存