Coil - 基于Kotlin协程的Android图片加载库 - 5

388 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

扩展图片管道线

Android天然支持多种图片格式, 然而依然有大量的格式它不支持(如GIF, SVG, MP4等等)

幸运的是, ImageLoader支持可插拔组件添加缓存层, 新的数据类型, 新的获取行为, 新的图片编码, 甚至覆盖基础的图片加载行为. Coil的图片管道线由5个主要部分组成, 这些部分按照如下顺序执行: InterceptorsMappersKeyersFetchersDecoders.

自定义组件必须在通过ComponentRegistry构建ImageLoader时添加进ImageLoader实例:

val imageLoader = ImageLoader.Builder(context)
    .components {
        add(CustomCacheInterceptor())
        add(ItemMapper())
        add(HttpUrlKeyer())
        add(CronetFetcher.Factory())
        add(GifDecoder.Factory())
    }
    .build()

Interceptor

Interceptor允许你观察, 转换, 短路或者将请求在ImageLoader图片引擎中重试. 比如, 可以像这样添加自定义缓存层:

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,
                dataSource = DataSource.MEMORY_CACHE
            )
        }
        return chain.proceed(chain.request)
    }
}

Interceptor是高级特性, 可以让自定义逻辑添加进ImageLoader的图片管道线. 这些实现重度依赖于OkHttp的Interceptor接口.

Mapper

Mapper允许你添加对自定义数据类型的支持. 举个例子, 我们从服务器获得这个模型:

data class Item(
    val id: Int,
    val imageUrl: String,
    val price: Int,
    val weight: Double
)

我们可以写自定义mapper将该数据结构映射成URL, 并稍后在管道线中处理:

class ItemMapper : Mapper<Item, String> {
    override fun map(data: Item, options: Options) = data.imageUrl
}

在构建ImageLoader时注册Mapper, 我们可以安全地加载Item:

val request = ImageRequest.Builder(context)
    .data(item)
    .target(imageView)
    .build()
imageLoader.enqueue(request)

Keyer

Keyer将数据转化成缓存key的一部分. 它的值用作MemoryCache.Key.key, 在请求的输出写入MemoryCache的时候.

Fetcher

Fetcher将数据(如URL, URI, File等)翻译成ImageSource或者Drawable. 它们通常将转入数据转化成Decoder能够消费的格式. 使用这个接口来添加对自定义获取机制(如Cronet, 自定义URI scheme等等)的支持.

Decoder

Decoder读取ImageSource然后返回Drawable. 使用这个接口来添加对自定义文件格式(如GIF, SVG, TIFF等等)的支持.