Coil — 是什么、核心概念以及 Android 中的 ImageLoader

作者: IT Sectr 发布日期: 2026-05-05 阅读时间: 9 分钟

Coil — 是一个用于在 Android 上加载图片的库,用 Kotlin 编写并基于协程构建。根据官方文档,该库支持 Memory Cache、Disk Cache 以及硬件加速的变换。Coil 以其最小的 APK 大小(约 150 KB)和与 Jetpack Compose 的完全兼容性而脱颖而出。

要点

  • Coil — 用于在 Android 上加载图片的库,使用 Kotlin Coroutines 和 Kotlin Serialization。
  • ImageLoader — 管理请求、缓存和图片变换的核心组件。
  • Memory Cache 将解码后的位图图像存储在 RAM 中以实现即时访问。
  • Disk Cache 将压缩文件保存在磁盘上,用于离线工作和减少流量。
  • Jetpack Compose — 该库支持 AsyncImage 和 SubcomposeAsyncImage 用于声明式 UI。

什么是 Coil?

Coil(Coroutine Image Loader)— 是一个用于在 Android 上加载图片的库,完全用 Kotlin 编写并使用协程进行异步操作。它提供了一个统一的 API,用于从网络、资源、文件系统和 Content Provider 加载位图图像,并具有自动的多级缓存。

与 Glide 和 Picasso 不同,Coil 使用 Kotlin Coroutines 代替回调链,使代码更加线性和可预测。所有加载和解码操作通过 Dispatchers.IO 在后台线程执行,结果不需要显式切换即可传递到主线程。

Coil 支持变换(Round、Blur、Grayscale)、过渡动画、SVG 和 GIF,以及用于非标准显示的自定义 Target。根据 Google I/O 2023,Coil 与 Glide 一起被推荐在官方的 Jetpack Compose 教程中使用。

  • APK 大小 — 约 150 KB(对比 Glide 的 500 KB)
  • 最低 Android 版本 — API 21(Lollipop)
  • 依赖 — Kotlin Coroutines(内置)

Coil 如何工作:ImageLoader 和 ImageRequest

ImageLoader — Coil 的主要组件,负责执行加载请求和管理缓存。每个实例包含对 MemoryCache、DiskCache、BitmapPool 和协程池的引用。默认情况下使用通过 Coil.imageLoader(context) 创建的单例。

ImageRequest

ImageRequest — 描述单个图片加载请求的对象:数据源(URL、URI、Int 资源)、目标 ImageView 或 Target、变换、缓存设置和占位图。ImageRequest 通过构建器构建,提供了灵活性和可读性。

kotlin
val request = ImageRequest.Builder(context)
    .data("https://example.com/image.jpg")
    .crossfade(true)
    .size(512, 512)
    .transformations(listOf(RoundedCornersTransformation(12f)))
    .memoryCachePolicy(CachePolicy.ENABLED)
    .diskCachePolicy(CachePolicy.ENABLED)
    .target(imageView)
    .build()

构建完成后,ImageRequest 通过 enqueueexecute 传递给 ImageLoader。enqueue 方法启动一个协程并返回 Disposable,允许在离开屏幕时取消加载。execute 方法是一个挂起函数,直接返回 Result。

请求执行流程

ImageLoader 依次检查 MemoryCache、DiskCache,只有当两者都未命中时才通过 HttpEngine 执行网络请求。加载完成后,字节根据目标大小解码为 Bitmap,应用变换,结果保存到两个缓存中并传递给 Target。

  • Memory Cache — 首先检查,键 — URL + 参数
  • Disk Cache — 内存中不存在时检查,键 — URL 的 MD5
  • HttpEngine — 默认是 OkHttp,可通过组件自定义

Coil 的主要组件

Coil 基于组件化架构构建,可以通过 依赖注入 替换任何部分。所有组件都在 ImageLoaderFactory 中注册,并通过构建器传递给 ImageLoader 的构造函数。

ImageLoader

ImageLoader — 所有加载操作的入口点。每个实例包含协程池、BitmapPool、MemoryCache、DiskCache 和拦截器列表。默认情况下创建一个全局实例,但对于模块化测试,可以创建具有隔离缓存的单独实例。

MemoryCache

MemoryCache — 基于 LRU(最近最少使用)的内存缓存,存储解码后的 Bitmap 对象。默认最大大小是应用程序可用内存的 25%,但不少于 32 MB。缓存键由 URL + 大小 + 变换组成,排除了提供过时图像的可能性。

DiskCache

DiskCache — 用于原始数据(JPEG、PNG、WebP)和解码后元数据的文件缓存。位于应用程序的缓存目录中,支持超出限制时的自动清理。磁盘操作通过 DiskCache.Builder 执行,配置目录和最大大小。

Coil 中的缓存级别

Coil 实现了多级缓存策略,最大限度地减少网络请求并加快图像显示。每个级别都有自己的目的和数据生命周期。

级别存储类型生命周期默认大小
Memory Cache内存中的 Bitmap直到 LRU 淘汰25% 堆,从 32 MB 起
Disk CacheJPEG/WebP 文件直到超过限制250 MB
Http CacheOkHttp 响应根据 Cache-Control 头取决于 HTTP 客户端

Memory Cache 提供对已解码位图的即时访问。Disk Cache 确保应用程序在首次加载后无需网络即可工作(离线优先)。Http Cache 在 OkHttp 级别处理条件请求 ETag 和 If-Modified-Since。

缓存策略通过 CachePolicy 按请求配置,具有三个值:ENABLED、READ_ONLY、WRITE_ONLY、DISABLED。例如,对于用户头像,可以为 Memory Cache 设置 READ_ONLY,为 Disk Cache 设置 ENABLED。

在 Kotlin 中使用 Coil 的示例

Coil 根据应用架构提供了多种集成方式。让我们通过工作代码示例来看三个关键场景。

通过扩展加载到 ImageView

load — ImageView 的扩展函数,是用一行代码加载图片的最简单方式。该函数接受 URL、URI、Int 资源或 File,并通过 lambda 配置器接受所有可选参数。

kotlin
imageView.load("https://example.com/photo.jpg") {
    crossfade(true)
    placeholder(R.drawable.placeholder)
    error(R.drawable.error)
    size(300, 300)
    transformations(CircleCropTransformation())
}

load 方法返回一个 Disposable,可以在 onDestroy 中或 View 被重用时取消。这可以防止快速滚动列表时的内存泄漏和不必要的网络请求。

在 Jetpack Compose 中使用

AsyncImage — 用于在声明式 UI 中加载图片的可组合函数。接受任何数据源和三个可选的状态参数:placeholder、error 和 success。

kotlin
@Composable
fun NetworkImage(url: String) {
    AsyncImage(
        model = url,
        contentDescription = "网络图片",
        placeholder = ColorPainter(Color.Gray),
        error = ColorPainter(Color.Red)
    )
}

SubcomposeAsyncImage — 更灵活的版本,允许通过内容插槽自定义加载过程中的显示。这对于骨架屏(shimmer)和进度条非常有用。

用于非标准输出的自定义 Target

如果 ImageView 或 AsyncImage 不合适,可以实现只有一个 onSuccess 方法的 Target,该方法接受 Bitmap。这用于加载到 Notification、RemoteViews 或 OpenGL 纹理。

kotlin
val target = object : BitmapTarget() {
    override fun onSuccess(result: Bitmap) {
        notificationRemoteView.setImageViewBitmap(R.id.icon, result)
    }
}

imageLoader.enqueue(
    ImageRequest.Builder(context)
        .data(url)
        .target(target)
        .build()
)

Coil 与其他库的比较

图片加载库的选择取决于项目需求。Coil 与 Glide 和 Picasso 竞争,每个都有自己的优势。主要特性的比较如下表所示。

特性CoilGlidePicasso
语言Kotlin(100%)Java + KotlinJava
APK 大小~150 KB~500 KB~120 KB
协程内置否(回调)否(回调)
Jetpack Compose原生支持通过 Accompaniment第三方
GIF/WebP是(内置)是(内置)
Google 推荐是(I/O 2023)

对于 Kotlin 和 Jetpack Compose 的新项目,Coil 由于零额外协程依赖和最小尺寸成为自然选择。Glide 仍然是复杂场景(如动画和视频预览)的首选。Picasso 在功能上不如两者,但在简单性上胜出。

在 Android 项目中配置 Coil

将 Coil 连接到 Android 项目通过 Gradle 依赖完成。添加后,库通过 ContentProvider 自动注册 ImageLoader,因此不需要在 Application 中手动初始化。如果需要自定义,通过构建器创建自己的 ImageLoader。

kotlin
// build.gradle.kts(应用模块)
dependencies {
    implementation("io.coil-kt:coil:2.6.0")
    // Jetpack Compose 额外添加:
    implementation("io.coil-kt:coil-compose:2.6.0")
    // 用于 SVG 支持:
    implementation("io.coil-kt:coil-svg:2.6.0")
    // 用于 GIF 支持:
    implementation("io.coil-kt:coil-gif:2.6.0")
}

用于自定义 ImageLoader 的是 ImageLoaderFactory — 在 Application.onCreate 中创建的单例。在工厂中可以配置缓存限制、HTTP 客户端、自定义解码器和日志记录。默认情况下,Coil 使用带有现成连接池的 OkHttp。

kotlin
class App : Application(), ImageLoaderFactory {
    override fun newImageLoader(): ImageLoader {
        return ImageLoader.Builder(this)
            .memoryCache {
                MemoryCache.Builder()
                    .maxSizePercent(0.25)
                    .build()
            }
            .diskCache {
                DiskCache.Builder()
                    .directory(cacheDir.resolve("coil_cache"))
                    .maxSizeBytes(512 * 1024 * 1024)
                    .build()
            }
            .build()
    }
}

常见问题

Coil 是什么,用于什么?

Coil — 用于在 Android 上加载图片的库,用 Kotlin 编写并使用协程。用于从网络、资源或文件系统异步加载、缓存和显示位图图像。

Coil 与 Glide 有什么不同?

Coil 100% 用 Kotlin 编写,使用 协程 代替 Glide 中的回调机制。Coil 具有更小的 APK 大小(~150 KB vs ~500 KB)和通过 AsyncImage 提供的 Jetpack Compose 原生支持。

如何将 Coil 添加到 Kotlin 项目?

在 build.gradle.kts 中添加依赖 io.coil-kt:coil:2.6.0。对于 Jetpack Compose,还要添加 io.coil-kt:coil-compose:2.6.0。库会自动通过 ContentProvider 注册 ImageLoader。

Coil 支持哪些图片类型?

Coil 支持 JPEG、PNG、WebP、BMP、SVG(通过 coil-svg 模块)和 GIF(通过 coil-gif 模块)。AVIF 和 HEIF 格式通过自定义解码器在 Android 10+ 设备上得到支持。

如何在 Coil 中配置缓存?

缓存通过 ImageLoader.Builder 配置:memoryCache 指定堆的百分比,diskCache 指定路径和以字节为单位的限制。缓存策略(ENABLED、DISABLED、READ_ONLY)通过 CachePolicy 按请求配置。

总结

  • Coil — Kotlin 中的图片加载库,完全支持协程和 Jetpack Compose。
  • ImageLoader 管理请求、缓存和变换,使用两个缓存级别:Memory Cache 和 Disk Cache。
  • AsyncImageSubcomposeAsyncImage 提供与 Compose 的集成,支持 placeholder、error 和 success 状态。
  • APK 大小 ~150 KB 使 Coil 成为市场上最紧凑的图片加载库之一。
  • 变换(RoundedCorners、CircleCrop、Blur)内置于库中,并通过硬件加速工作。
  • Disk Cache 提供对以前加载的图像的离线访问,具有可配置的存储限制。
  • Coil 被 Google 推荐 在官方的 Jetpack Compose 指南中,这证实了其作为现代标准的地位。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读