Glide.preload()

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、尺寸、裁剪变换等参数,要尽量和真正显示时一致,否则缓存可能命中不了。
暂无评论

发送评论 编辑评论


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