Android 图片加载 · 新手教程

Android Coil 新手使用教程

从零上手 Coil,搞懂 1.x / 2.x / 3.x 的差异,选对主流版本

📦 最新稳定版 3.5.0 🟢 当前主流:Coil 3.x ⏱️ 更新于 2026-08

一、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.xCoil 2.xCoil 3.x(主流)
状态已停止维护稳定,仍被广泛使用当前主流,持续更新
平台仅 Android仅 AndroidKotlin Multiplatform:Android / iOS / JVM / JS / WASM
Maven 坐标io.coil-kt:coilio.coil-kt:coilio.coil-kt.coil3:coil
包名coilcoilcoil3
最低 API16 / 172123(3.5.0 起,此前为 21)
Compose 用法rememberImagePainterAsyncImage / SubcomposeAsyncImage / rememberAsyncImagePainter同 2.x,且支持 Compose Multiplatform
网络加载内置 OkHttp内置 OkHttp解耦,需引入 coil-network-okhttp 或 coil-network-ktor
磁盘缓存依赖 OkHttp 的 Cache自带 DiskCache(可中断解码)自带 DiskCache
图片接口DrawableDrawable自定义 coil3.Image(非 Android 端用 Skiko 渲染)
Bitmap 池已移除已移除
默认 ScaleFILLFITFIT
版本管理手动写版本号手动写版本号支持 BOM 统一版本
3.x 最大的两个变化: ① 变成真正的 Kotlin 多平台库(一套图片逻辑跑 Android + iOS + 桌面 + Web);② 把网络依赖拆出去了,想要网络加载必须显式加 coil-network-okhttpcoil-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 用 AsyncImagemodel 参数,传的值类型和上面完全对应:

来源ImageView 写法Compose model 写法
网络load(url)model = url
drawableload(R.drawable.x)model = R.drawable.x
mipmapload(R.mipmap.ic_launcher)model = R.mipmap.ic_launcher
本地文件load(file)model = file
相册 Uriload(uri)model = uri
Bitmapload(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:coilio.coil-kt.coil3:coilimport coilimport coil3(可与 2.x 共存,但会引入两套依赖)。
  • 网络组件解耦:必须显式添加 coil-network-okhttpcoil-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:旧的 Parameters API 被 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)公开资料 · 仅供学习参考