图片加载(Coil/Glide):Coil与Glide对比、图片加载配置、占位图与错误图

图片加载,几乎是每个App都绕不开的坎。我见过不少项目,前期随便用个图片库,结果到了后期,OOM、列表卡顿、图片变形……各种问题全冒出来了。说白了,选对图片加载库,就是给App的稳定性上了一道保险。

今天咱们就来聊聊Kotlin项目里最主流的两个选择:CoilGlide。我会从对比、配置、占位图与错误图这几个维度,把我的实战经验掰开揉碎讲给你听。

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有个坑:默认会使用ImageViewScaleType,如果你没设置,图片可能会被拉伸。我刚开始用Glide时就吃过这个亏。

小技巧:无论用哪个库,都建议在加载前先设置好ImageViewScaleType。我一般用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的核心对比、配置要点、以及占位图/错误图的使用场景都串起来了。

图片加载知识体系 图片加载库 Coil Glide 纯Kotlin · 协程原生 包体积小(~150KB) API简洁 · 扩展函数 生态成熟 · 坑少 原生支持GIF/WebP 适合老项目维护 占位图 · 错误图 · 尺寸配置 · 缓存策略

5. 实战中的一些碎碎念

最后,分享几个我踩过的坑,希望能帮你省点时间:

  • 缓存策略别乱改:Coil和Glide的默认缓存策略已经够用了。我见过有人为了省空间把磁盘缓存关了,结果每次启动都要重新下载,流量哗哗的。
  • 列表加载时注意复用:在RecyclerView里,ImageView会被复用。如果你不取消上一个请求,可能会出现「图片闪烁」的问题。Coil和Glide都自动处理了,但如果你用自定义View,记得手动取消。
  • 大图加载要谨慎:我曾经在项目里加载一张4000x3000的图片,直接OOM。后来加了size()限制,问题解决。记住:永远不要加载超过屏幕尺寸的图片

总结一下:Coil和Glide都是好库,选哪个取决于你的项目场景。配置上,占位图和错误图是基本功,别偷懒。尺寸和缓存策略,按需调整,别过度优化。

好了,今天就聊到这儿。希望这些经验对你有帮助。


公众号:蓝海资料掘金营,微信deep3321