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

580 阅读3分钟

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

Artifacts

Coil在mavenCentral()发布了8个库:

  • io.coil-kt:coil: 是默认库, 依赖了io.coil-kt:coil-base库, 创建了单例ImageLoader, 而且包含ImageView的扩展函数.
  • io.coil-kt:coil-base: 是io.coil-kt:coil库的子集,  不包含单例ImageLoaderImageView的扩展函数.
  • io.coil-kt:coil-compose: 包含了对Jetpack Compose的支持.
  • io.coil-kt:coil-compose-base: 是io.coil-kt:coil-compose库的子集, 但不包含依赖于单例ImageLoader的函数.
  • io.coil-kt:coil-gif: 包括2个解码器以支持解码GIF. 查看GIF更多细节.
  • io.coil-kt:coil-svg: 包含1个解码器以支持解码SVG. 查看SVG更多细节.
  • io.coil-kt:coil-video: 包含1个decoder以支持解码来自[Android支持的任何视频格式]的帧(developer.android.com/guide/topic…). 查看video更多细节.
  • io.coil-kt:coil-bom: 包含材料清单. coil-bom的导入允许你在没有声明版本的情况下对其它Coil库进行依赖.

Image Loader

ImageLoader是服务类, 用于执行ImageRequestImageLoader处理缓存, 数据获取, 图片解码, 请求管理, Bitmap池技术, 内存管理等等.

默认的Coil库(io.coil-kt:coil)导入单例ImageLoader, 它可以通过扩展函数访问: context.imageLoader.

单例ImageLoader可以在Application类中通过实现ImageLoaderFactory接口进行配置:

class MyApplication : Application(), ImageLoaderFactory {

    override fun newImageLoader(): ImageLoader {
        return ImageLoader.Builder(this)
            .crossfade(true)
            .build()
    }
}

ImageLoaderFactory的实现是可选的. 如果你没有实现, Coil会通过默认值懒创建ImageLoader.

点击完整文档查看更多信息.

Image Requests

ImageRequest是被ImageLoader执行的值类. 它描述了图片应该从哪里加载, 图片如何加载, 和其它额外的参数. ImageLoader有2个可以执行请求的函数:

  • enqueue: 将ImageRequest入队, 以在后台线程异步执行 to be executed asynchronously on a background thread.
  • execute: 在当前协程执行ImageRequest并且返回ImageResult.

所有请求都应该设置data (例如url, uri, file, drawable resource等等). 这是ImageLoader要用来决定从哪获取图片数据的地方. 如果没有设置data, 它的默认值为NullRequestData.

此外, 你可能想在入队请求时设置target. 它是可选的, 但target是接收已加载的占位符/成功/失败图片资源的地方. 已执行请求会返回拥有成功/失败图片资源的ImageResult.

这里有个例子:

// enqueue
val request = ImageRequest.Builder(context)
    .data("https://www.example.com/image.jpg")
    .target(imageView)
    .build()
val disposable = imageLoader.enqueue(request)

// execute
val request = ImageRequest.Builder(context)
    .data("https://www.example.com/image.jpg")
    .build()
val result = imageLoader.execute(request)

ImageView扩展函数

io.coil-kt:coil库提供了ImageView扩展函数的集合. 这里是将URL加载进ImageView的例子:

imageView.load("https://www.example.com/image.jpg")

上面的调用等价于:

val imageLoader = imageView.context.imageLoader
val request = ImageRequest.Builder(imageView.context)
    .data("https://www.example.com/image.jpg")
    .target(imageView)
    .build()
imageLoader.enqueue(request)

ImageView.load可以通过可选的尾置lambda参数进行配置:

imageView.load("https://www.example.com/image.jpg") {
    crossfade(true)
    placeholder(R.drawable.image)
    transformations(CircleCropTransformation())
}

查看文档以获取更多信息.

所支持的数据类型

被全部ImageLoader实例支持的基础数据类型是:

  • String (映射成Uri)
  • HttpUrl
  • Uri (android.resourcecontentfilehttp, 和https)
  • File
  • @DrawableRes Int
  • Drawable
  • Bitmap
  • ByteArray
  • ByteBuffer

所支持的图片格式

ImageLoader支持下面全部的非动画文件类型:

  • BMP
  • JPEG
  • PNG
  • WebP
  • HEIF (Android 8.0+)

此外, Coil有扩展库支持下面的文件类型:

  • coil-gif: GIF, WebP动画(Android 9.0+), HEIF动画(Android 11.0+)
  • coil-svg: SVG
  • coil-video: 来自Android支持的视频编解码的全部静态视频帧

预加载

要图片预加载进内存, 可在没有Target的情况下将ImageRequest执行或者入队:

val request = ImageRequest.Builder(context)
    .data("https://www.example.com/image.jpg")
    // Optional, but setting a ViewSizeResolver will conserve memory by limiting the size the image should be preloaded into memory at.
    .size(ViewSizeResolver(imageView))
    .build()
imageLoader.enqueue(request)

要仅想将网络图片加载进磁盘缓存, 需要将request禁用内存缓存:

val request = ImageRequest.Builder(context)
    .data("https://www.example.com/image.jpg")
    .memoryCachePolicy(CachePolicy.DISABLED)
    .build()
imageLoader.enqueue(request)

取消请求

ImageRequest在下面的用例下会自动地取消:

  • request.lifecycle达到了DESTROYED状态.
  • request.target是一个ViewTarget而且它的View已经解绑.

此外, ImageLoader.enqueue返回Disposable, 它可用于处置请求(取消请求并释放其相关资源):

val disposable = imageView.load("https://www.example.com/image.jpg")

// Cancel the request.
disposable.dispose()