Glide.preload() 的作用一句话说就是:
提前把图片加载到 Glide 的缓存里,但不立刻显示到 ImageView。
这样等你真正调用 into(imageView) 显示图片时,Glide 可以直接从内存缓存或磁盘缓存中取,图片显示会更快,减少白屏、闪烁和等待。
1. preload() 是干什么的?
平时我们加载图片:
Glide.with(context)
.load(url)
.into(imageView)
这表示:
下载 / 读取图片
→ 解码
→ 缩放
→ 放入缓存
→ 显示到 ImageView
而 preload() 是:
Glide.with(context)
.load(url)
.preload()
它表示:
提前下载 / 读取图片
→ 解码
→ 缩放
→ 放入缓存
→ 不显示
也就是说,preload() 的重点是:
提前加载,提前缓存,不绑定 ImageView 显示
2. 一个简单例子
假设你有一个商品列表,用户即将滑到下一页图片。
你可以提前预加载:
Glide.with(context)
.load(nextImageUrl)
.preload()
等用户真的滑到那张图片时:
Glide.with(context)
.load(nextImageUrl)
.into(imageView)
这时 Glide 很可能已经缓存好了图片,所以显示更快。
3. preload() 和 into(imageView) 的区别
into(imageView)
Glide.with(context)
.load(url)
.into(imageView)
意思是:
加载图片,并显示到指定 ImageView
preload()
Glide.with(context)
.load(url)
.preload()
意思是:
只加载图片,不显示
对比一下:
| 方法 | 是否显示图片 | 是否会缓存 | 常见用途 |
|---|---|---|---|
into(imageView) |
会显示 | 会 | 正常显示图片 |
preload() |
不显示 | 会 | 提前加载图片 |
4. preload() 会加载到哪里?
preload() 加载完成后,资源会进入 Glide 的缓存体系,可能包括:
MemoryCache 内存缓存
DiskCache 磁盘缓存
当你后面再次用同样的请求加载:
Glide.with(context)
.load(url)
.into(imageView)
Glide 就可能命中缓存。
注意,是“可能”,不是 100%。
因为缓存能否命中取决于:
URL 是否相同
尺寸是否相同
Transformation 是否相同
Options 是否相同
Signature 是否相同
内存缓存是否被清理
磁盘缓存策略
5. preload() 最重要的点:尺寸要一致
这是很多人用 preload() 没效果的主要原因。
比如你预加载时这样写:
Glide.with(context)
.load(url)
.preload()
但真正显示时:
Glide.with(context)
.load(url)
.override(300, 300)
.centerCrop()
.into(imageView)
这两个请求不完全一样,缓存 Key 可能不同,导致不能很好命中缓存。
更推荐预加载时也写上相同尺寸和变换:
Glide.with(context)
.load(url)
.override(300, 300)
.centerCrop()
.preload()
真正显示时:
Glide.with(context)
.load(url)
.override(300, 300)
.centerCrop()
.into(imageView)
这样缓存命中率更高。
6. preload(width, height)
preload() 有一个重载方法:
preload(width, height)
例如:
Glide.with(context)
.load(url)
.centerCrop()
.preload(300, 300)
它表示:
提前加载一张 300x300 左右、经过 centerCrop 处理的图片
这和下面写法类似:
Glide.with(context)
.load(url)
.override(300, 300)
.centerCrop()
.preload()
7. RecyclerView 中为什么要用 preload?
在图片列表中,如果用户快速滑动,正常加载流程可能是:
Item 出现在屏幕上
→ 开始加载图片
→ 等待网络/磁盘/解码
→ 图片显示
用户就会看到:
占位图
空白
闪一下
图片出来
如果提前预加载下一批图片:
用户还没滑到
→ Glide 已经开始加载下一批图片
→ 用户滑到时直接显示缓存
体验会更顺滑。
8. RecyclerView 中简单预加载示例
比如你在列表滑动时,提前加载后面 5 张图片:
fun preloadNextImages(
context: Context,
urls: List<String>,
currentPosition: Int
) {
val preloadCount = 5
val end = minOf(currentPosition + preloadCount, urls.size)
for (i in currentPosition until end) {
Glide.with(context)
.load(urls[i])
.override(300, 300)
.centerCrop()
.preload()
}
}
然后在滑动时调用:
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(rv: RecyclerView, dx: Int, dy: Int) {
val layoutManager = rv.layoutManager as LinearLayoutManager
val lastVisible = layoutManager.findLastVisibleItemPosition()
preloadNextImages(this@MainActivity, imageUrls, lastVisible + 1)
}
})
不过实际项目中,更推荐使用 Glide 提供的 RecyclerView 预加载工具。
9. Glide RecyclerViewPreloader
Glide 官方提供了专门给 RecyclerView 用的预加载类:
RecyclerViewPreloader
它可以根据滑动方向,自动提前加载即将出现的图片。
大概使用思路是:
val preloader = RecyclerViewPreloader(
Glide.with(this),
modelProvider,
sizeProvider,
maxPreload
)
recyclerView.addOnScrollListener(preloader)
这里几个参数含义:
modelProvider:告诉 Glide 预加载哪些 URL
sizeProvider:告诉 Glide 图片预加载尺寸
maxPreload:最多提前加载多少张
10. preload() 返回值是什么?
preload() 返回的是一个 Target<TranscodeType>:
val target = Glide.with(context)
.load(url)
.preload()
你可以保存这个 target,必要时取消:
Glide.with(context).clear(target)
但普通场景中通常不需要手动保存。
11. preload() 和 submit() 的区别
Glide 里还有一个方法叫 submit()。
preload()
Glide.with(context)
.load(url)
.preload()
主要用于:
提前加载到缓存
不关心拿到 Bitmap 对象
submit()
val futureTarget = Glide.with(context)
.asBitmap()
.load(url)
.submit()
主要用于:
后台加载图片,并且你想拿到结果对象
例如:
Thread {
val bitmap = Glide.with(context)
.asBitmap()
.load(url)
.submit()
.get()
// 使用 bitmap
}.start()
区别:
| 方法 | 是否显示 | 是否直接拿结果 | 常见用途 |
|---|---|---|---|
preload() |
不显示 | 不直接拿结果 | 提前缓存 |
submit() |
不显示 | 可以 .get() 拿到 Bitmap/File |
后台获取图片对象 |
12. 使用 preload() 的注意事项
1. 不要预加载太多
预加载太多会造成:
占用网络
占用 CPU 解码
占用内存
影响当前正在显示的图片加载
例如 RecyclerView 中提前 3~10 张比较常见,不要一次 preload 几百张。
2. 预加载请求要和真正显示请求一致
例如真正显示:
Glide.with(context)
.load(url)
.override(200, 200)
.circleCrop()
.into(imageView)
预加载也应该尽量一样:
Glide.with(context)
.load(url)
.override(200, 200)
.circleCrop()
.preload()
3. 注意生命周期
建议用:
Glide.with(fragment)
或者:
Glide.with(activity)
不要随便长期用 applicationContext,否则请求生命周期不容易跟页面绑定。
4. 根据网络情况使用
如果用户是移动网络,你一次预加载很多大图,可能会浪费流量。
可以根据业务控制:
Wi-Fi 下多预加载
移动网络少预加载或不预加载
13. 一句话总结
preload() 的作用是:
提前把图片加载进 Glide 缓存,但不显示到 ImageView。
它适合:
RecyclerView 图片列表
Banner 下一张图
相册/商品详情页下一屏图片
大图预览前提前加载
关键注意:
预加载时的 URL、尺寸、裁剪变换等参数,要尽量和真正显示时一致,否则缓存可能命中不了。