Skip to content

Coil: 现代化图片加载库 Coil 3.x

源:Coil 官方文档 | Coil 中文文档 (第三方翻译)

Coil (Coroutines Image Loader) 是 Android 官方推荐的现代化图片加载库。它是首个完全基于 Kotlin 协程、Okio 和 OkHttp 构建的图片库。相比于传统的 Glide 或 Fresco,Coil 具有更轻量级的体积、原生支持 Jetpack Compose、以及天然适配 Kotlin Multiplatform (KMP) 的架构。

技术价值与核心优势

  • 协程驱动:完全利用协程进行异步操作,避免了回调地狱,并能自动与 Android 生命周期(Lifecycle)同步。
  • 性能卓越:采用 Segment 内存模型(通过 Okio)和智能内存池,显著降低了 GC 压力。
  • 零样板代码:API 设计符合 Kotlin 惯例,支持大量的扩展函数,使得图片加载代码极度简洁。
  • 架构领先:Coil 3.x 已全面转向 KMP 架构,支持在 Android、iOS 和 Desktop 之间共享图片加载逻辑。

依赖配置与版本

查看 Maven Central 最新版本

kotlin
dependencies {
    // 基础核心库
    implementation("io.coil-kt.coil3:coil:3.0.4")
    // Jetpack Compose 扩展支持
    implementation("io.coil-kt.coil3:coil-compose:3.0.4")
    // 网络引擎支持 (如 OkHttp)
    implementation("io.coil-kt.coil3:coil-network-okhttp:3.0.4")
}
groovy
dependencies {
    implementation 'io.coil-kt.coil3:coil:3.0.4'
    implementation 'io.coil-kt.coil3:coil-compose:3.0.4'
    implementation 'io.coil-kt.coil3:coil-network-okhttp:3.0.4'
}
toml
[versions]
coil = "3.0.4"

[libraries]
coil-core = { group = "io.coil-kt.coil3", name = "coil", version.ref = "coil" }
coil-compose = { group = "io.coil-kt.coil3", name = "coil-compose", version.ref = "coil" }
coil-network = { group = "io.coil-kt.coil3", name = "coil-network-okhttp", version.ref = "coil" }

核心抽象:ImageLoader 与 Request

Coil 的操作主要围绕两个核心对象展开。

API 核心签名

kotlin
public interface ImageLoader : Closeable {
    // 默认配置
    public val defaults: DefaultRequestOptions
    // 核心执行函数
    public suspend fun execute(request: ImageRequest): ImageResult
    // 异步排队函数
    public fun enqueue(request: ImageRequest): Disposable
}

public class ImageRequest {
    public val data: Any?               // 支持 String, Uri, File, Drawable 等
    public val target: Target?          // 加载目标
    public val lifecycle: Lifecycle     // 生命周期绑定
    public val placeholder: Drawable?   // 占位图
}

实战演练:Compose 与 View 加载

Jetpack Compose 中的集成

Coil 提供了 AsyncImage 组件,专门针对 Compose 的重组机制进行了优化。

kotlin
import coil3.compose.AsyncImage

@Composable
fun UserProfile(avatarUrl: String) {
    AsyncImage(
        model = avatarUrl,
        contentDescription = "User Avatar",
        modifier = Modifier.size(64.dp).clip(CircleShape)
    )
}
kotlin
import coil3.compose.SubcomposeAsyncImage

@Composable
fun AdvancedImage(avatarUrl: String) {
    SubcomposeAsyncImage(
        model = avatarUrl,
        contentDescription = null
    ) {
        val state = painter.state
        if (state is AsyncImagePainter.State.Loading) {
            CircularProgressIndicator() // 加载中显示进度条
        } else {
            AsyncImageContent()
        }
    }
}

底层原理:拦截器与磁盘缓存

Coil 的工作流由一系列 Interceptor 组成,类似于 OkHttp。当发起一个请求时,它会依次经过 EngineInterceptor、MappedInterceptor 和 DecoderInterceptor。

深度剖析:Okio 磁盘缓存是如何提升性能的?

Coil 丢弃了 Java IO 的流式读取,转而使用 OkioFileSystem

  1. 高效预读:利用 Okio 的 Source 缓冲机制,减少了从闪存读取数据时的 CPU 周期。
  2. 零拷贝中转:在将图片从网络写入磁盘时,通过 Segment 转移直接操作内存块,大幅降低了堆内存分配频率。
  3. LRU 策略:内部实现了一个严谨的 LRU 缓存策略,确保磁盘占用不会无限增长。

工程实践准则

单例 ImageLoader

应当实现 SingletonImageLoader.Factory 接口,在 Application 层级配置全局共享的缓存池和网络引擎。严禁在每个页面重复创建 ImageLoader,以避免内存浪费。

位图重用与内存抖动

Coil 默认启用了位图池(Bitmap Pooling)。在处理长列表(RecyclerView)时,确保图片尺寸(Size)经过精确裁剪,避免加载过大的 Bitmap 导致 OOM。

R8/Proguard 配置

由于 Coil 依赖于 Kotlin 协程和 Okio,需保留相关元数据:

proguard
-keep class coil3.** { *; }
-dontwarn coil3.**