本文已参与「新人创作礼」活动,一起开启掘金创作之路。
扩展图片管道线¶
Android天然支持多种图片格式, 然而依然有大量的格式它不支持(如GIF, SVG, MP4等等)
幸运的是, ImageLoader支持可插拔组件添加缓存层, 新的数据类型, 新的获取行为, 新的图片编码, 甚至覆盖基础的图片加载行为. Coil的图片管道线由5个主要部分组成, 这些部分按照如下顺序执行: Interceptors, Mappers, Keyers, Fetchers和Decoders.
自定义组件必须在通过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等等)的支持.