Administrator
发布于 2026-08-25 / 13 阅读
0
0

系列文章《Android 工程师的 100 篇进阶笔记》第 36 篇:图片加载框架对比:Coil vs Glide 深度解析

上一篇聊了主题系统,这篇继续 UI 方向,聊一个每个 App 都要面对的选择——图片加载框架。Glide 是老牌选手,Coil 是后起之秀。到底该选哪个?

两者的背景

Glide 由 Google 的 Sam Judd 创建,2014 年开源,经过多年迭代,功能极其全面。在国内使用率极高,几乎成了"默认选择"。

Coil 由 Instacart 的 Tyler Wong 创建,2020 年开源。名字是 "Coroutine Image Loader" 的缩写,核心卖点是基于 Kotlin 协程和 OkIO。

核心对比

维度

Glide

Coil

语言

Java + Kotlin

纯 Kotlin

线程模型

线程池 + Future

Kotlin 协程

API 风格

Builder 链式

DSL + 协程

Compose 支持

通过 Accompanist 适配

原生 AsyncImage

包体积

~500KB

~200KB(依赖 OkIO)

代码量

~40K 行

~10K 行

维护状态

Google 维护,更新偏慢

社区维护,更新活跃

GIF 支持

内置

需要扩展库

基础用法对比

Glide:

Glide.with(context)
    .load("https://example.com/image.jpg")
    .placeholder(R.drawable.placeholder)
    .error(R.drawable.error)
    .crossFade()
    .into(imageView)

Coil:

imageView.load("https://example.com/image.jpg") {
    placeholder(R.drawable.placeholder)
    error(R.drawable.error)
    crossfade(true)
}

Coil 的 DSL 写法更简洁,且类型安全。Glide 的 Builder 模式更经典,Java 代码也能用。

Compose 支持

这是 Coil 的明显优势。Coil 直接提供了 AsyncImage 组件:

AsyncImage(
    model = "https://example.com/image.jpg",
    contentDescription = "头像",
    placeholder = painterResource(R.drawable.placeholder),
    error = painterResource(R.drawable.error),
    contentScale = ContentScale.Crop,
    modifier = Modifier.size(48.dp)
)

Glide 在 Compose 中需要通过 Accompanist-Glide 或官方 GlideImage(较新版本):

GlideImage(
    model = "https://example.com/image.jpg",
    contentDescription = "头像",
    loading = { CircularProgressIndicator() },
    failure = { Text("加载失败") }
)

Glide 的 Compose 支持在改进中,但体验和原生度不如 Coil。

缓存策略

两者的三级缓存思路类似:

  • 内存缓存:LruCache 存 Bitmap

  • 磁盘缓存:存原始数据或解码后的 Bitmap

  • 网络:下载

Glide 缓存特点:

  • 默认缓存原始数据 + 解码后 Bitmap

  • 支持按尺寸缓存(同一张图不同 size 可能缓存多份)

  • diskCacheStrategy 控制缓存策略

Glide.with(context)
    .load(url)
    .diskCacheStrategy(DiskCacheStrategy.ALL)
    .override(targetWidth, targetHeight) // 指定尺寸减少内存
    .into(imageView)

Coil 缓存特点:

  • 默认按 URL + size 做 key

  • 支持自定义 Cache Key

  • 协程管理缓存读写,取消加载更干净

imageView.load(url) {
    memoryCachePolicy(policy = CachePolicy.ENABLED)
    diskCachePolicy(policy = CachePolicy.ENABLED)
    size(48.toPx()) // 指定目标尺寸
}

Coil 取消加载是个亮点:因为底层是协程,当 ImageView 的 Composable 被移出组合时协程自动取消,不会出现"加载完但 View 已销毁"的问题。

生命周期感知

Glide 的 with(context) 会自动绑定 Activity/Fragment 生命周期,在 onStop 时暂停加载,onStart 时恢复。

Coil 也做了同样的事,底层通过 LifecycleCoroutineScope 实现。两者在这点上差距不大。

内存管理

Glide 的 Bitmap Pool 是它的杀手锏。它会复用已回收的 Bitmap 内存区域,减少 GC 抖动。在列表滚动频繁创建/回收 Bitmap 的场景下效果明显。

Coil 也有 BitmapPool,但实现方式不同。它依赖 OkIO 的内存管理,在 Kotlin Native 上也能复用。不过在纯 Android 场景下,Glide 的 Bitmap Pool 更成熟。

怎么选

我的建议:

  • 新项目 + Compose 为 UI 框架:直接 Coil。原生 Compose 支持、API 简洁、包体积小。

  • 新项目 + View 体系:两者都行。如果团队 Kotlin 为主选 Coil,Java 为主选 Glide。

  • 存量项目已用 Glide:不用急着换。Glide 依然强大且稳定,迁移成本不划算。

  • 需要 GIF/WebP 支持:Glide 内置支持更好。Coil 需要加 coil-gif 扩展。

  • 需要视频帧加载:Glide 内置支持。Coil 需要 coil-video 扩展。

迁移注意事项

如果你决定从 Glide 迁移到 Coil:

  1. Coocil 的 load() 会自动处理 ImageView scaleType,但如果你之前手动 override 了尺寸,需要手动指定 size()。

  2. Glide 的 transform 和 Coil 的 transformations API 不同,自定义变换需要改写。

  3. 圆角、圆形等常见变换 Coil 用 CircleCropTransformation、RoundedCornersTransformation,注意导包。

  4. Coil 默认不做 Downsampling,大图加载要注意 OOM。

小结

Coil 和 Glide 不是替代关系,各有适用场景。Coil 在 Compose 时代有原生优势,Glide 在稳定性和功能全面性上依然能打。选哪个取决于项目技术栈和团队习惯。

下一篇聊聊 Android 无障碍开发。


评论