Coil:官方推荐的Kotlin图片加载库

共 7781字,需浏览 16分钟

 ·

2021-05-21 13:12

前言

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名
  • 参与方式:「点击文章右下角”在看“ -> 回复截图到公众号 即可,我将从中随机抽取」

    点击“在看”就能升职 & 加薪水哦!



浏览 78
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐