Coil:官方推荐的Kotlin图片加载库
前言
coil,一个面世时间很短的图片加载库:在 2020 年 10 月 22 日才发布了 1.0.0 版本,但却受到了 Android 官方的推广。本文主要介绍
定义 特点 原理 基础使用 常用功能 扩展功能
定义
Coroutine Image Loader,一个完全使用 Kotlin 撰写的图片加载库。
// 在 mavenCentral()进行下载
implementation("io.coil-kt:coil:1.1.1")
特点
功能强大:完全使用 Kotlin 撰写,运用了大量 Kotlin特性,尤其是协程;并使用了大量Kotlin常用的开源库,如okhttp、okio 和 AndroidX Lifecycles等; 使用简单:充分利用 Kotlin 的语法特性且包含丰富的拓展函数,减少了许多样板代码; 性能好:对于图片加载的性能优化做得十分出色,如内存缓存、磁盘缓存、通过 BitmapPool 循环利用 Bitmap、自动暂停和取消网络请求等; 占存少、量级轻:整个开源库仅 2000余个方法,相对比 Glide 和 Fresco 要轻量非常多。
原理
通过 Kotlin 协程来进行图片加载。其实从名字Coil的由来可知:Coroutine Image Loader,Coroutine即协程。
关于Kotlin协程相关可以看文章:Kotlin:协程到底是什么何方神圣?
基础使用
主要是进行图片的加载。
// 加载网络图片
imageView.load("https://www.example.com/image.jpg")
// 加载本地资源图片
imageView.load(R.drawable.image)
// 加载文件里的图片
imageView.load(File("/path/to/image.jpg"))
// 使用 lambda 语法进行图片加载及对应配置
imageView.load("https://www.example.com/testimage.jpg") {
crossfade(true)
placeholder(R.drawable.image)
transformations(CircleCropTransformation())
}
常用功能
图片加载管理器:ImageLoader 图片加载请求:ImageRequest 取消图片加载:Disposable 图片变换:Transformation
1. 图片加载管理器:ImageLoader
作用:负责处理图片缓存、数据获取、图像解码、请求管理、Bitmap 缓存池、内存管理等工作。
val imageLoader = ImageLoader.Builder(context)
.availableMemoryPercentage(0.25)
.crossfade(true)
.build()
需要特别注意的是:为了达到性能最优,建议只创建一个 ImageLoader & 进行共享。主要原因是每个 ImageLoader 都有自己的内存缓存和 Bitmap 缓存池。
2. 图片加载请求:ImageRequest
作用:为 ImageLoader 加载图片提供所有的必要信息。
val request = ImageRequest.Builder(context)
.data("https://www.example.com/image.jpg")
.target { drawable ->
// Handle the result.
}
.build()
context.imageLoader.enqueue(request)
ImageRequest 基于 设计模式中的建造者模式来进行创建,包含了加载图片的各个配置项,主要包括:

3. 取消图片加载:Disposable
作用:取消图片加载,是调用 load() 方法后的返回值。
interface Disposable {
/**
* 如果图片加载请求已经完成或者取消,则返回 true
*/
val isDisposed: Boolean
/**
* 取消正在进行的图片加载请求以及释放相关的资源,而且该方法是幂等的
*/
fun dispose()
/**
* 非阻塞式地等待任务结束
*/
@ExperimentalCoilApi
suspend fun await()
}
4. 图片变换:Transformation
interface Transformation {
fun key(): String
suspend fun transform(pool: BitmapPool, input: Bitmap, size: Size): Bitmap
}
imageView.load("https://www.example.com/image.jpg") {
transformations(CircleCropTransformation())
}
Coil 提供的图片变换的效果包括:

扩展功能
拦截器:Interceptors 映射器:Mappers 抓取器:Fetchers 解码器:Decoders
1. 拦截器:Interceptors
作用:对图片加载请求进行观察、转换、重试或缓存。(借鉴了 okhttp 的设计思想)
class CustomCacheInterceptor(
private val context: Context,
private val cache: LruCache<String, Drawable>
) : Interceptor {
override suspend fun intercept(chain: Interceptor.Chain): ImageResult {
val value = cache.get(chain.request.data.toString())
if (value != null) {
return SuccessResult(
drawable = value.bitmap.toDrawable(context),
request = chain.request,
metadata = TODO()
)
}
return chain.proceed(chain.request)
}
}
2. 映射器(Mappers) 与 抓取器(Fetchers)
映射器(Mappers):实现不同数据类型之间的转换 抓取器(Fetchers):将图片地址转换成 BufferedSource 或 Drawable
二者一般是配合使用,可以对图片资源类型进行区分,具体如下:
// 加载本地和网络图片
imageView.load("android.resource://example.package.name/drawable/image")
imageView.load("https://www.example.com/image.jpg")
// StringMapper 会将传入的 String 转换为对应的 Uri。
internal class StringMapper : Mapper<String, Uri> {
override fun map(data: String) = data.toUri()
}
// ResourceUriFetcher 会判断 Uri 的 scheme 类型是否为 android.resource,是的话代表本地资源文件
// HttpUriFetcher 则判断 Uri 的 scheme 是否为 http 或 https,是的话代表网络图片。
internal class HttpUriFetcher(callFactory: Call.Factory) : HttpFetcher<Uri>(callFactory) {
override fun handles(data: Uri) = data.scheme == "http" || data.scheme == "https"
override fun key(data: Uri) = data.toString()
override fun Uri.toHttpUrl(): HttpUrl = HttpUrl.get(toString())
}
常见的Mappers主要包括:

3. 解码器:Decoders
Coil 提供了很多Android不支持解码的图片格式的对应解码库,如:Gif、SVG、视频帧等。
/**
* 解码gif
*/
// 1. 下载地址
implementation("io.coil-kt:coil-gif:1.1.1")
// 2. 具体使用
val imageLoader = ImageLoader.Builder(context)
.componentRegistry {
if (SDK_INT >= 28) {
add(ImageDecoderDecoder())
} else {
add(GifDecoder())
}
}
.build()
/**
* 解码SVG
*/
// 1. 下载地址
implementation("io.coil-kt:coil-svg:1.1.1")
// 2. 具体使用
val imageLoader = ImageLoader.Builder(context)
.componentRegistry {
add(SvgDecoder(context))
}
.build()
/**
* 视频帧
*/
// 1. 下载地址
implementation("io.coil-kt:coil-video:1.1.1")
// 2. 具体使用
val imageLoader = ImageLoader.Builder(context)
.componentRegistry {
add(VideoFrameFileFetcher())
add(VideoFrameUriFetcher())
}
.build()
官方文档
https://coil-kt.github.io/coil/
「Carson每天带你学习一个Android知识点」,长按扫描关注公众号。同时,期待您精彩文章的投稿:真诚邀请您来分享
最后福利:学习资料赠送

福利:由本人亲自撰写 & 整理的「Android学习方法资料」 数量:10名 参与方式:「点击文章右下角”在看“ -> 回复截图到公众号 即可,我将从中随机抽取」 点击“在看”就能升职 & 加薪水哦!
评论