一、Coil 是什么
Coroutine Image Loader —— 用协程写成的图片加载库
Coil 是一个 Kotlin 优先的 Android / 跨平台图片加载库,名字来自 Coroutine Image Loader。它的核心特点是:
- 协程优先:基于 Kotlin 协程,没有回调地狱,也不用桥接 RxJava / LiveData。
- 轻量:方法数约 2000,APK 增量小,远小于 Glide 等传统方案。
- Kotlin 原生体验:扩展函数、DSL 配置、内联优化,调用简洁。
- 格式齐全:JPEG、PNG、WebP、GIF、SVG、HEIF/HEIC、视频帧都能加载。
- UI 无侵入:
ImageView.load(...)与 Compose 的AsyncImage是一套统一加载逻辑。
一句话理解: 如果你的项目已经在用 Kotlin + 协程(尤其 Jetpack Compose),Coil 几乎不需要改动架构就能接入。
二、版本全景对比(1.x / 2.x / 3.x)
这是选型的地基,先看清三代版本的区别
1.x · 已停更 2019 起
2.x · 稳定可用 2.0–2.7
3.x · 主流 最新 3.5.0
| 维度 | Coil 1.x | Coil 2.x | Coil 3.x(主流) |
|---|---|---|---|
| 状态 | 已停止维护 | 稳定,仍被广泛使用 | 当前主流,持续更新 |
| 平台 | 仅 Android | 仅 Android | Kotlin Multiplatform:Android / iOS / JVM / JS / WASM |
| Maven 坐标 | io.coil-kt:coil | io.coil-kt:coil | io.coil-kt.coil3:coil |
| 包名 | coil | coil | coil3 |
| 最低 API | 16 / 17 | 21 | 23(3.5.0 起,此前为 21) |
| Compose 用法 | rememberImagePainter | AsyncImage / SubcomposeAsyncImage / rememberAsyncImagePainter | 同 2.x,且支持 Compose Multiplatform |
| 网络加载 | 内置 OkHttp | 内置 OkHttp | 解耦,需引入 coil-network-okhttp 或 coil-network-ktor |
| 磁盘缓存 | 依赖 OkHttp 的 Cache | 自带 DiskCache(可中断解码) | 自带 DiskCache |
| 图片接口 | Drawable | Drawable | 自定义 coil3.Image(非 Android 端用 Skiko 渲染) |
| Bitmap 池 | 有 | 已移除 | 已移除 |
| 默认 Scale | FILL | FIT | FIT |
| 版本管理 | 手动写版本号 | 手动写版本号 | 支持 BOM 统一版本 |
3.x 最大的两个变化: ① 变成真正的 Kotlin 多平台库(一套图片逻辑跑 Android + iOS + 桌面 + Web);② 把网络依赖拆出去了,想要网络加载必须显式加
coil-network-okhttp 或 coil-network-ktor,这也顺带让纯本地加载的应用可以不带任何网络库。三、现在该用哪个版本
结论先行,避免纠结
- 新项目(纯 Android 或 Compose 多平台):直接用 Coil 3.5.x。这是当前主流,特性最新、维护活跃。
- 存量 Android-only 项目:在用 Coil 2.x 完全没问题,生态成熟、资料多,可逐步迁移到 3.x。
- Coil 1.x:已过时,不推荐任何新项目使用;仅在维护极老代码时才会碰到。
选型提醒: Coil 3.x 最低 API 已提升到 23(3.5.0 起)。若你的应用还需支持 Android 5.0(API 21/22),要么留在 Coil 3.4.x 及更早,要么继续使用 Coil 2.x。
四、快速开始(以 Coil 3.x 为例)
在 build.gradle.kts 中引入依赖
方式一:逐条引入(最简单)
// build.gradle.kts (Module :app) dependencies { // 核心 + 网络(OkHttp 引擎) implementation("io.coil-kt.coil3:coil:3.5.0") implementation("io.coil-kt.coil3:coil-network-okhttp:3.5.0") // Jetpack Compose 集成 implementation("io.coil-kt.coil3:coil-compose:3.5.0") // 扩展格式(GIF / SVG 等,按需添加) implementation("io.coil-kt.coil3:coil-gif:3.5.0") // Android only implementation("io.coil-kt.coil3:coil-svg:3.5.0") // 跨平台 }
方式二:用 BOM 统一版本(多模块推荐)
多个模块都要用 Coil 时,用 BOM 锁定同一版本,避免各模块版本错配:
dependencies { // BOM 统一管理版本,下方无需再写版本号 implementation(platform("io.coil-kt.coil3:coil-bom:3.5.0")) implementation("io.coil-kt.coil3:coil") implementation("io.coil-kt.coil3:coil-network-okhttp") implementation("io.coil-kt.coil3:coil-compose") }
新手易错: Coil 3 以后不内置网络库。只写
coil 而不加 coil-network-okhttp,加载网络图片会失败。纯加载本地资源(drawable / file / res)则可不加。五、基础用法(详细):各种图片来源怎么加载
Coil 3 的
load(data) / AsyncImage(model) 能接收多种数据类型,下面按真实开发场景逐个讲核心认知: Coil 3 会根据
data 的类型自动选 Fetcher——网络地址走网络库,Int 当资源 ID,File/Uri 走本地/文件,Bitmap/ByteArray 直接解码。你几乎只要把「数据源」传进去,其余交给 Coil。5.1 加载网络图片(最常见:列表头像 / 商品图)
// 场景:RecyclerView 头像,要求渐显 + 失败兜底 + 圆形裁剪 import coil3.load import coil3.transform.CircleCropTransformation imageView.load("https://cdn.example.com/avatar/10086.png") { crossfade(true) placeholder(R.drawable.avatar_placeholder) // 加载中的占位 error(R.drawable.avatar_error) // 出错显示默认图 transformations(CircleCropTransformation()) // 圆形头像 size(96, 96) // 明确目标尺寸,省内存 }
性能习惯: 列表里尽量用
size() 或让 ImageView 自适应尺寸,Coil 会按显示尺寸下采样,避免把 2000px 大图原样解码进内存。5.2 加载 drawable 资源(App 内置图)
把资源 ID 直接传进去即可,Coil 会当成本地资源解码:
// 场景:引导页默认底图、空状态图、默认头像
imageView.load(R.drawable.empty_state)
imageView.load(R.drawable.default_banner)
5.3 加载 mipmap 资源(应用图标等)
重点: mipmap 和 drawable 一样,直接传资源 ID(R.mipmap.xxx) 即可,不需要拼 URI。
// 场景:关于页展示 App 图标、启动页 Logo、通知大图标预览 imageView.load(R.mipmap.ic_launcher) // 应用图标 imageView.load(R.mipmap.ic_launcher_round)
Coil 3 的坑: 3.x 不再支持
android.resource://包名/drawable/文件名 这种字符串 URI(会影响资源压缩)。必须用资源 ID(R.drawable.xxx / R.mipmap.xxx)或数字 ID 形式 android.resource://包名/12345678。老代码里写死的字符串资源 URI 要改成传 ID。5.4 加载本地文件 File(沙盒 / 缓存 / 下载目录)
// 场景:拍照保存到 filesDir、已下载的离线图、裁剪后临时文件 import java.io.File val file = File(context.filesDir, "user_avatar.jpg") imageView.load(file) // 直接传 File 对象 // 或传 file:// URI imageView.load(Uri.fromFile(file))
5.5 加载相册返回的 ContentProvider Uri(系统选择器)
// 场景:调用系统相册/拍照,onActivityResult 拿到的 content:// Uri import android.net.Uri private val pick = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? -> uri ?: return@registerForActivityResult imageView.load(uri) // 直接传 android.net.Uri } pick.launch("image/*")
系统相册返回的是
content:// 的 ContentProvider Uri,Coil 3 原生支持,无需你自己把流读到 File 再加载。5.6 加载 Bitmap / ByteArray(已存在于内存的数据)
// 场景:相机直接返回 Bitmap、接口下发图片二进制、加水印后的结果 imageView.load(bitmap) // 直接显示 Bitmap imageView.load(byteArray) // 直接解码 ByteArray
5.7 Compose 中各来源的写法对照
Compose 用 AsyncImage 的 model 参数,传的值类型和上面完全对应:
| 来源 | ImageView 写法 | Compose model 写法 |
|---|---|---|
| 网络 | load(url) | model = url |
| drawable | load(R.drawable.x) | model = R.drawable.x |
| mipmap | load(R.mipmap.ic_launcher) | model = R.mipmap.ic_launcher |
| 本地文件 | load(file) | model = file |
| 相册 Uri | load(uri) | model = uri |
| Bitmap | load(bitmap) | model = bitmap |
import coil3.compose.AsyncImage import coil3.request.ImageRequest import androidx.compose.ui.platform.LocalContext // Compose 中同样能配占位/变换,用 ImageRequest 包装 AsyncImage( model = ImageRequest.Builder(LocalContext.current) .data(R.mipmap.ic_launcher) .crossfade(true) .placeholder(R.drawable.ph) .build(), contentDescription = null, contentScale = ContentScale.Fit, )
5.8 监听加载状态(骨架屏 / 错误态)
import coil3.compose.SubcomposeAsyncImage import coil3.compose.SubcomposeAsyncImageContent import coil3.compose.AsyncImagePainter SubcomposeAsyncImage( model = "https://example.com/photo.jpg", contentDescription = null, ) { when (painter.state) { is AsyncImagePainter.State.Loading -> /* 显示骨架屏 */ is AsyncImagePainter.State.Error -> /* 显示错误重试按钮 */ else -> SubcomposeAsyncImageContent() } }
六、常用配置
占位、错误、渐变、变换、缩放
占位图 / 错误图 / 淡入
imageView.load(url) {
placeholder(R.drawable.placeholder) // 加载中
error(R.drawable.error) // 失败
fallback(R.drawable.fallback) // model 为 null 时
crossfade(300) // 300ms 渐显
}
变换:圆角 / 圆形 / 灰度
Coil 3 把变换合并进了 coil-core,直接导入即可:
import coil3.transform.CircleCropTransformation import coil3.transform.RoundedCornersTransformation import coil3.transform.GrayscaleTransformation imageView.load(url) { transformations( CircleCropTransformation(), // 圆形头像 // RoundedCornersTransformation(16f), // 圆角 16dp // GrayscaleTransformation(), // 灰度 ) }
缩放模式
imageView.load(url) {
scale(Scale.FILL) // 填满裁剪(默认是 FIT)
}
// Compose 中用 contentScale
AsyncImage(model = url, contentScale = ContentScale.Crop, ...)
七、进阶用法
自定义 ImageLoader、缓存、网络库、动图
1) 全局自定义 ImageLoader(Coil 3 的 SingletonImageLoader.Factory)
class MyApp : Application(), SingletonImageLoader.Factory { override fun newImageLoader(): ImageLoader { return ImageLoader.Builder(this) .diskCache { DiskCache.Builder() .directory(cacheDir.resolve("image_cache")) .maxSizePercent(0.02) // 最多占用 2% 空间 .build() } .memoryCacheMaxSizePercent(0.25) .crossfade(true) .build() } }
2) 网络库二选一
// A. OkHttp(Android / JVM 推荐,默认成熟稳定) implementation("io.coil-kt.coil3:coil-network-okhttp:3.5.0") // B. Ktor(跨平台 / 多端统一网络栈时选它) implementation("io.coil-kt.coil3:coil-network-ktor:3.5.0") implementation("io.ktor:ktor-client-okhttp:3.x") // 再配一个 Ktor 引擎
3) 加载 GIF / SVG / 视频帧
implementation("io.coil-kt.coil3:coil-gif:3.5.0") // GIF(Android only) implementation("io.coil-kt.coil3:coil-svg:3.5.0") // SVG(跨平台) implementation("io.coil-kt.coil3:coil-video:3.5.0") // 视频首帧 // GIF 使用方式与普通图片一致,Coil 自动识别格式 imageView.load("https://example.com/anim.gif")
记忆要点: GIF / 视频解码器目前仍是 Android only;SVG 解码器已支持多平台。需要跨端动图时,3.x 的多平台能力主要体现在静态图与 SVG 上。
八、从 Coil 2.x 迁移到 3.x 的破坏性变更
老项目升级时这几处必改
- 坐标与包名:
io.coil-kt:coil→io.coil-kt.coil3:coil,import coil→import coil3(可与 2.x 共存,但会引入两套依赖)。 - 网络组件解耦:必须显式添加
coil-network-okhttp或coil-network-ktor,否则网络图加载失败。 - ImageLoader 初始化:
Coil.setImageLoader(...)→ 在 Application 实现SingletonImageLoader.Factory并重写newImageLoader()。 - Drawable → Image:非 Android 平台用
coil3.Image;Android 上可用Drawable.asImage()/Image.asDrawable(resources)互相转换。 - Context → PlatformContext:自定义组件里
Context改为PlatformContext(Android 上仍是 Context 的别名)。 - Parameters → Extras:旧的
ParametersAPI 被Extras取代,key 改为基于对象身份(identity equality)。 - 最低 API:3.5.0 起最低 API 23,注意兜底低版本设备。
九、总结与选型建议
- 新手直接上 Coil 3.5.x:跨平台、BOM 版本管理、网络解耦,是当下最值得学的版本。
- 核心三步:① 加依赖(核心 + 网络 + 可选格式)→ ②
ImageView.load()或AsyncImage加载 → ③ 用 builder 配 placeholder / 变换 / 缩放。 - 别踩两个坑:3.x 忘了加网络库会加载不出图;最低 API 23 要留意老设备。
- 老项目:Coil 2.x 依旧稳,可渐进迁移,不必强求。
下一步: 官方文档 coil-kt.github.io/coil 有完整的 API 与样例;想做 Compose 多平台图片加载,直接参考 Coil 3 的 samples 仓库。
本教程由 WorkBuddy 整理 · 内容基于 Coil 3.5.0(2026-06)公开资料 · 仅供学习参考