glide 缓存

Glide 的“三级缓存”通常指:

活动资源缓存 ActiveResources → 内存缓存 MemoryCache → 磁盘缓存 DiskCache

它的目的就是:同一张图片不要重复解码、重复下载,尽量快地显示出来,并减少内存和网络消耗。


一、Glide 三级缓存整体流程

假设你写了:

Glide.with(context)
    .load(url)
    .into(imageView)

Glide 大致会按这个顺序找图片:

1. ActiveResources 活动资源缓存
   ↓ 没有
2. MemoryCache 内存缓存
   ↓ 没有
3. DiskCache 磁盘缓存
   ↓ 没有
4. 网络 / 文件 / Uri 等原始数据源加载

也就是说:

先看当前正在用的图片有没有
再看内存里有没有
再看磁盘里有没有
最后才去网络下载

二、第一级:ActiveResources 活动资源缓存

1. 它是什么?

ActiveResources 可以理解为:

当前正在被页面使用、正在显示的图片资源。

例如:

imageView.setImageBitmap(bitmap)

这张图片此刻正在某个 ImageView 上显示,那么它就可能存在于 ActiveResources 中。


2. 为什么要有 ActiveResources?

假设一个列表中多个地方使用同一张图片:

ImageView A 显示 avatar.png
ImageView B 也显示 avatar.png

如果 A 已经在显示这张图片,B 再加载同一张图片时,Glide 可以直接从 ActiveResources 拿到,不用再去内存缓存或磁盘缓存找。


3. 特点

ActiveResources 的特点:

速度最快
不需要重新解码
图片正在被使用
一般通过弱引用/引用计数管理

它不是传统意义上“给你长期保存图片”的缓存,而是管理正在使用中的资源


三、第二级:MemoryCache 内存缓存

1. 它是什么?

MemoryCache 是真正意义上的内存缓存,通常基于 LruCache 实现。

Lru 的意思是:

Least Recently Used,最近最少使用。

也就是说:

最近用过的图片留在内存里
很久没用的图片会被移除

2. 举个例子

比如你有一个 RecyclerView 图片列表。

你往下滑:

第 1 张图片离开屏幕
第 2 张图片离开屏幕
第 3 张图片离开屏幕

这些图片不再显示了,Glide 会尝试把它们从 ActiveResources 移到 MemoryCache。

如果你又往回滑:

第 1 张图片重新进入屏幕

Glide 就可以直接从内存缓存取出来,速度非常快。


3. MemoryCache 的优点

速度快
不需要重新读取磁盘
不需要重新网络下载
不需要重新完整解码

4. MemoryCache 的限制

内存缓存容量有限。

如果图片太多,Glide 不可能全部放在内存中,否则会 OOM。

所以它会按照 Lru 规则清理旧图片。


四、第三级:DiskCache 磁盘缓存

1. 它是什么?

DiskCache 是磁盘缓存,图片会被缓存到手机本地存储中。

相比内存缓存:

读取速度比内存慢
但是容量更大
App 进程被杀后仍然可能存在
可以避免重复网络下载

2. DiskCache 缓存的是什么?

Glide 的磁盘缓存主要可以分两类:

原始数据缓存 Data Cache
转换后资源缓存 Resource Cache

五、DiskCache 的两种缓存

1. Data Cache:原始数据缓存

比如你加载一张网络图片:

Glide.with(this)
    .load("https://example.com/a.jpg")
    .into(imageView)

Glide 从网络下载到的是原始图片数据,例如:

a.jpg 原图数据

这个就是 Data Cache。

它还没有经过:

缩放
裁剪
圆角
模糊
centerCrop
transform

2. Resource Cache:处理后资源缓存

如果你这样写:

Glide.with(this)
    .load(url)
    .centerCrop()
    .override(200, 200)
    .into(imageView)

Glide 最终显示的不是原图,而是经过处理后的图片:

原图 → 解码 → 缩放成 200x200 → centerCrop → 显示

这个处理后的结果就可以缓存为 Resource Cache。

下次再加载同样尺寸、同样变换的图片时,Glide 可以直接从 Resource Cache 里拿,不用重新解码和裁剪。


六、完整加载流程

可以把 Glide 的加载流程理解成这样:

开始加载图片
   ↓
查 ActiveResources
   ↓ 如果有,直接显示

没有
   ↓
查 MemoryCache
   ↓ 如果有,移到 ActiveResources,然后显示

没有
   ↓
查 Resource Disk Cache
   ↓ 如果有,读取处理后的图片,放入内存,然后显示

没有
   ↓
查 Data Disk Cache
   ↓ 如果有,读取原始图片数据,解码、变换、放入内存,然后显示

没有
   ↓
从网络 / 文件 / Uri 等数据源加载
   ↓
缓存到磁盘
   ↓
解码、变换
   ↓
放入内存
   ↓
显示到 ImageView

七、用一张图表示

Glide.with().load().into()

        ↓

┌──────────────────────┐
│ 1. ActiveResources   │  正在使用的资源
└──────────────────────┘
        ↓ miss

┌──────────────────────┐
│ 2. MemoryCache       │  内存 LruCache
└──────────────────────┘
        ↓ miss

┌──────────────────────┐
│ 3. DiskCache         │  磁盘缓存
│  - Resource Cache    │  处理后的图片
│  - Data Cache        │  原始图片数据
└──────────────────────┘
        ↓ miss

┌──────────────────────┐
│ 4. Source            │  网络、文件、Uri、资源等
└──────────────────────┘

八、ActiveResources 和 MemoryCache 的区别

很多人容易混淆这两个。

ActiveResources

正在使用中的图片
比如当前 ImageView 正在显示
优先级最高
速度最快

MemoryCache

暂时不用但还留在内存里的图片
比如 RecyclerView 滑出屏幕后缓存起来
方便下次快速复用

举个例子:

图片正在屏幕上显示:
ActiveResources

图片滑出屏幕,但还没被清理:
MemoryCache

图片 App 重启后还想复用:
DiskCache

九、Glide 缓存 Key 是什么?

Glide 判断“两次请求是不是同一张图片”,不是只看 URL。

它会根据一系列条件生成缓存 Key,例如:

图片 URL / 文件路径
图片尺寸 override(width, height)
图片变换 centerCrop、circleCrop、roundedCorners
签名 signature
资源类型 Bitmap / Drawable / Gif
Options 参数

所以:

Glide.with(this)
    .load(url)
    .override(100, 100)
    .into(imageView1)

和:

Glide.with(this)
    .load(url)
    .override(300, 300)
    .into(imageView2)

虽然 URL 一样,但尺寸不同,缓存 Key 可能不同。


十、常用缓存控制 API

1. 跳过内存缓存

Glide.with(this)
    .load(url)
    .skipMemoryCache(true)
    .into(imageView)

意思是:

不放入内存缓存
但不代表不使用磁盘缓存

注意:一般不建议随便关内存缓存。


2. 设置磁盘缓存策略

Glide.with(this)
    .load(url)
    .diskCacheStrategy(DiskCacheStrategy.ALL)
    .into(imageView)

常见策略:

DiskCacheStrategy.ALL

缓存原始数据和处理后的资源。

DiskCacheStrategy.DATA

只缓存原始数据。

DiskCacheStrategy.RESOURCE

只缓存处理后的资源。

DiskCacheStrategy.NONE

不使用磁盘缓存。

DiskCacheStrategy.AUTOMATIC

默认策略,Glide 自动判断。


十一、DiskCacheStrategy 怎么选?

1. 普通网络图片

一般直接用默认即可:

Glide.with(this)
    .load(url)
    .into(imageView)

Glide 默认会选择合适的缓存策略。


2. 如果想最大程度缓存

Glide.with(this)
    .load(url)
    .diskCacheStrategy(DiskCacheStrategy.ALL)
    .into(imageView)

适合图片不经常变、希望二次加载很快的场景。


3. 如果图片经常变化但 URL 不变

比如头像 URL 不变,但图片内容变了。

可以加 signature

Glide.with(this)
    .load(url)
    .signature(ObjectKey(version))
    .into(imageView)

例如:

Glide.with(this)
    .load(avatarUrl)
    .signature(ObjectKey(userAvatarUpdateTime))
    .into(imageView)

userAvatarUpdateTime 变化时,Glide 会认为这是新图片,重新加载。


十二、清除缓存

1. 清除内存缓存

必须在主线程调用:

Glide.get(context).clearMemory()

2. 清除磁盘缓存

必须在子线程调用:

Thread {
    Glide.get(context).clearDiskCache()
}.start()

十三、一句话总结

Glide 的三级缓存是:

ActiveResources:当前正在显示的图片,最快
MemoryCache:内存中的 Lru 缓存,滑动列表时复用
DiskCache:磁盘缓存,避免重复下载和重复处理

加载顺序是:

ActiveResources → MemoryCache → DiskCache → 网络/文件源

其中磁盘缓存又分为:

Resource Cache:处理后的图片
Data Cache:原始图片数据
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇