图片加载(Coil/Glide):Coil与Glide对比、图片加载配置、占位图与错误图
图片加载,几乎是每个App都绕不开的坎。我见过不少项目,前期随便用个图片库,结果到了后期,OOM、列表卡顿、图片变形……各种问题全冒出来了。说白了,选对图片加载库,就是给App的稳定性上了一道保险。
今天咱们就来聊聊Kotlin项目里最主流的两个选择:Coil和Glide。我会从对比、配置、占位图与错误图这几个维度,把我的实战经验掰开揉碎讲给你听。
1. Coil vs Glide:到底选哪个?
先别急着站队。我个人的习惯是:新项目用Coil,老项目维护用Glide。为什么?咱们看个对比表就清楚了。
| 维度 | Coil | Glide |
|---|---|---|
| 语言 | 纯Kotlin,协程原生 | Java + Kotlin混合 |
| 包体积 | 约150KB | 约500KB(含依赖) |
| 缓存策略 | 内存 + 磁盘(LRU) | 内存 + 磁盘(LRU) |
| GIF/WebP | 支持(需额外配置) | 原生支持 |
| API风格 | 扩展函数 + 链式调用 | 链式调用 |
| 协程支持 | 一等公民 | 需额外适配 |
你看,Coil最大的优势就是轻量 + Kotlin原生。如果你项目里全是Kotlin,用Coil简直不要太爽。Glide呢?生态更成熟,坑更少,尤其处理复杂动图时更稳。
我的建议:如果团队Kotlin经验丰富,选Coil;如果项目历史包袱重,或者需要大量处理GIF,Glide更稳妥。
2. 图片加载配置:从入门到实战
配置这东西,说白了就是「怎么让图片加载得又快又好」。我拿Coil举例,因为它的配置方式更符合Kotlin的直觉。
2.1 基础配置
先加依赖。在build.gradle.kts里写上:
implementation("io.coil-kt:coil:2.6.0")
然后,在Application里初始化。嗯,这里有个小细节:Coil默认是懒加载的,你第一次调用load()时才会初始化。但我建议还是显式配置一下:
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
// 我个人习惯在这里配置全局参数
ImageLoader.Builder(this)
.memoryCachePolicy(CachePolicy.ENABLED)
.diskCachePolicy(CachePolicy.ENABLED)
.crossfade(true)
.build()
}
}
2.2 加载图片的几种姿势
Coil的API设计得很优雅。你看:
// 最基础用法
imageView.load("https://example.com/image.jpg")
// 带配置的用法
imageView.load("https://example.com/image.jpg") {
placeholder(R.drawable.placeholder)
error(R.drawable.error)
size(300, 300)
crossfade(500)
// 我曾经遇到过一个坑:不设置size,大图直接OOM
// 所以建议总是显式指定目标尺寸
}
为什么会这样?因为Coil默认会使用ImageView的尺寸,但如果你在RecyclerView里复用,尺寸可能不对。显式指定,最安全。
2.3 Glide的配置方式
Glide的配置稍微啰嗦一点,但也很清晰:
// 基础用法
Glide.with(this)
.load("https://example.com/image.jpg")
.placeholder(R.drawable.placeholder)
.error(R.drawable.error)
.override(300, 300)
.into(imageView)
注意看,Glide的override()和Coil的size()是一个意思。但Glide有个坑:默认会使用ImageView的ScaleType,如果你没设置,图片可能会被拉伸。我刚开始用Glide时就吃过这个亏。
小技巧:无论用哪个库,都建议在加载前先设置好ImageView的ScaleType。我一般用CENTER_CROP,适合大多数场景。
3. 占位图与错误图:用户体验的细节
占位图和错误图,说白了就是「网络不好时给用户看什么」。别小看这个,我见过不少App,网络一慢就白屏,用户直接关掉。
3.1 占位图(Placeholder)
占位图的作用是:在图片加载完成前,先显示一个默认图。这样用户不会觉得页面是空的。
// Coil
imageView.load(url) {
placeholder(R.drawable.ic_placeholder)
// 我习惯用一张纯色背景+logo的图,既简单又专业
}
// Glide
Glide.with(this)
.load(url)
.placeholder(R.drawable.ic_placeholder)
.into(imageView)
嗯,这里要注意:占位图不要太大。我曾经见过有人用一张高清大图做占位图,结果加载占位图本身就要好几秒,完全失去了意义。建议用矢量图或者小尺寸的PNG。
3.2 错误图(Error)
错误图是加载失败时显示的。比如网络断了、图片被删了、URL写错了……
// Coil
imageView.load(url) {
error(R.drawable.ic_error)
// 还可以设置fallback,当url为空时显示
fallback(R.drawable.ic_empty)
}
// Glide
Glide.with(this)
.load(url)
.error(R.drawable.ic_error)
.fallback(R.drawable.ic_empty)
.into(imageView)
你想想看,如果用户看到一张裂开的图片,是不是很影响心情?所以错误图最好设计得「友好」一点,比如加个「点击重试」的提示。
避坑指南:我曾经在项目里犯过一个错——把占位图和错误图设成了同一张图。结果用户根本分不清是「正在加载」还是「加载失败」。后来我改成:占位图用灰色背景+旋转动画,错误图用红色背景+感叹号。体验瞬间好了很多。
4. 知识体系总览
为了让你更直观地理解,我画了一张图。这张图把Coil和Glide的核心对比、配置要点、以及占位图/错误图的使用场景都串起来了。
5. 实战中的一些碎碎念
最后,分享几个我踩过的坑,希望能帮你省点时间:
- 缓存策略别乱改:Coil和Glide的默认缓存策略已经够用了。我见过有人为了省空间把磁盘缓存关了,结果每次启动都要重新下载,流量哗哗的。
- 列表加载时注意复用:在RecyclerView里,
ImageView会被复用。如果你不取消上一个请求,可能会出现「图片闪烁」的问题。Coil和Glide都自动处理了,但如果你用自定义View,记得手动取消。 - 大图加载要谨慎:我曾经在项目里加载一张4000x3000的图片,直接OOM。后来加了
size()限制,问题解决。记住:永远不要加载超过屏幕尺寸的图片。
总结一下:Coil和Glide都是好库,选哪个取决于你的项目场景。配置上,占位图和错误图是基本功,别偷懒。尺寸和缓存策略,按需调整,别过度优化。
好了,今天就聊到这儿。希望这些经验对你有帮助。