【奇淫巧技】新的图片加载库?基于Kotlin协程的图片加载库——Coil

新的图片加载库——Coil

Coil 是 Kotlin 团队研发的新的的图片加载库,它使用了不少高级功能,例如协程,Okhttpandroidx.lifecycleCoil 还包括一些高级功能,例如图像采样,有效的内存使用以及请求的自动取消/暂停java

默认状况下 Coil 与 R8 彻底兼容,开箱即用,不须要添加额外的规则。若是使用 Proguard ,您可能须要为 Coroutines, OkHttpOkio 添加规则android

Coil 的优点

  • 快速: Coil 进行了不少优化,包括内存和磁盘缓存,对内存中的图像进行采样,从新使用位图,自动暂停/取消请求等等
  • 轻量: Coil 在您的 APK 中添加了约 2000 种方法(对于已经使用 OkHttpCoroutines 的应用程序),与 Picasso 至关,远少于 GlideFresco
  • 易用: Coil 的 API 利用 Kotlin 的特性简化了样板代码
  • 现代: CoilKotlin-first,使用现代化的库,例如 Coroutines, OkHttp, Okio, 以及 AndroidX Lifecycles

Coil 是如下名称的缩写:Coroutine Image Loadergit

Artifacts

Coil 拥有 5 个 artifact 并发布在 mavenCentral()github

  • io.coil-kt:coil:依赖于 io.coil-kt:coil-base 而且包含了 Coil 的单例和 ImageView.load 的扩展函数
  • io.coil-kt:coil-base:base 库, 不包含 Coil 的单例和 ImageView.load 的扩展函数,若是使用依赖注入,则可使用该库
  • io.coil-kt:coil-gif:引入一系列解码器以支持解码 gif
  • io.coil-kt:coil-svg:引入一系列解码器以支持 svg
  • io.coil-kt:coil-video:包括两个 fetchers ,以支持从 Android 支持的任何视频格式中提取和解码帧
// 普通使用引用
implementation "io.coil-kt:coil:0.11.0" // 使用依赖注入时或者制做基于 coil 的库引用 implementation "io.coil-kt:coil-base:0.11.0" 复制代码

Java 8

Coil 要求 Java 8,要经过 D8 启用 Java 8 调试,请将如下内容添加到 Gradle 脚本web

Gradle (.gradle)api

android {
 compileOptions {  sourceCompatibility JavaVersion.VERSION_1_8  targetCompatibility JavaVersion.VERSION_1_8  } }  tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {  kotlinOptions {  jvmTarget = "1.8"  } } 复制代码

Gradle Kotlin DSL (.gradle.kts)缓存

android {
 compileOptions {  sourceCompatibility = JavaVersion.VERSION_1_8  targetCompatibility = JavaVersion.VERSION_1_8  } }  tasks.withType<KotlinCompile> {  kotlinOptions {  jvmTarget = "1.8"  } } 复制代码

使用

ImageView 扩展函数

io.coil-kt:coil 提供了 类型安全的 ImageView 扩展函数安全

在 ImageView 中加载图片,只需调用 load 扩展函数网络

// URL
imageView.load("https://www.example.com/image.jpg")  // Resource imageView.load(R.drawable.image)  // File imageView.load(File("/path/to/image.jpg"))  // And more... 复制代码

上面的请求等价于:并发

val imageLoader = Coil.imageLoader(context)
val request = LoadRequest.Builder(imageView.context)  .data("https://www.example.com/image.jpg")  .target(imageView)  .build() imageLoader.execute(request) 复制代码

可选的请求配置能够经过 lambda 来操做

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

Image Loaders

ImageLoader 是执行请求的服务类。 他们处理缓存,数据获取,图像解码,请求管理,bitmap pool,内存管理等。 可使用 builder 来建立和配置新实例:

val imageLoader = ImageLoader.Builder(context)
 .availableMemoryPercentage(0.25)  .crossfade(true)  .build() 复制代码

imageView.load 使用单例 ImageLoader 执行 LoadRequest 。 可使用如下方式访问单例 ImageLoader

val imageLoader = Coil.imageLoader(context)
复制代码

(可选)您能够建立本身的 ImageLoader 实例,并经过依赖项注入将它们注入:

val imageLoader = ImageLoader(context)
复制代码

当您建立单个 ImageLoader 并在整个应用程序中共享时,Coil 的性能最佳。 这是由于每一个 ImageLoader 都有本身的内存缓存,bitmap pool 和网络监听

Requests

有两种 Request 类型

若是要加载到自定义 target 中,能够执行 LoadRequest

val request = LoadRequest.Builder(context)
 .data("https://www.example.com/image.jpg")  .target { drawable ->  // Handle the result.  }  .build() imageLoader.execute(request) 复制代码

要强制获取图像,请执行 GetRequest:

val request = GetRequest.Builder(context)
 .data("https://www.example.com/image.jpg")  .build() val drawable = imageLoader.execute(request).drawable 复制代码

单例

若是您使用的是 io.coil-kt:coil ,您可使用如下任意方式设置 ImageLoader 的实例

在 Application 中实现 ImageLoaderFactory(推荐)

class MyApplication : Application(), ImageLoaderFactory {
  override fun newImageLoader(): ImageLoader {  return ImageLoader.Builder(context)  .crossfade(true)  .okHttpClient {  OkHttpClient.Builder()  .cache(CoilUtils.createDefaultCache(context))  .build()  }  .build()  } } 复制代码

调用 Coil.setImageLoader

val imageLoader = ImageLoader.Builder(context)
 .crossfade(true)  .okHttpClient {  OkHttpClient.Builder()  .cache(CoilUtils.createDefaultCache(context))  .build()  }  .build() Coil.setImageLoader(imageLoader) 复制代码

默认的 ImageLoader 能够经过这样取回

val imageLoader = Coil.imageLoader(context)
复制代码

设置默认的 ImageLoader 是可选的。 若是未设置,则 Coil 会延迟建立具备默认值的 ImageLoader

若是您使用的是 io.coil-kt:coil-base,您应建立本身的 ImageLoader 实例并经过依赖注入将它注入到 app 中

注意:若是设置自定义 OkHttpClient,则必须设置缓存实现,不然 ImageLoader 将没有磁盘缓存。 可使用 CoilUtils.createDefaultCache 建立默认的 Coil 缓存实例

支持的数据类型

ImageLoader 支持的数据类型为

  • String (mapped to a Uri)
  • HttpUrl
  • Uri ( android.resource, content, file, http, and https schemes only)
  • File
  • @DrawableRes Int
  • Drawable
  • Bitmap

预加载

若是要预加载到内存中,执行一个不带 target 的 LoadRequest

val request = LoadRequest.Builder(context)
 .data("https://www.example.com/image.jpg")  // 可选的,可是设置 ViewSizeResolver 能够经过限制预加载的大小来节省内存  .size(ViewSizeResolver(imageView))  .build() imageLoader.execute(request) 复制代码

若是只想将网络图片预加载到磁盘中,能够为 request 关闭内存缓存

val request = LoadRequest.Builder(context)
 .data("https://www.example.com/image.jpg")  .memoryCachePolicy(CachePolicy.DISABLED)  .build() imageLoader.execute(request) 复制代码

取消请求

LoadRequest 会自动取消在如下几种状况下

  • 关联的 view detached,

  • 关联的 lifecycle destroyed

  • 另外一个 request 在相同的 view 中开启

此外,每一个 LoadRequest 返回一个 RequestDisposable,可用于检查请求是否在运行中或处理该请求(有效地取消请求并释放其关联资源)

val disposable = imageView.load("https://www.example.com/image.jpg")
 // Cancel the request. disposable.dispose() 复制代码

GetRequest 仅当协程的上下文被取消时才会取消

图片采样

假设磁盘上有一个 500x500 的映像,可是只须要以 100x100 的大小将其加载到内存中便可在视图中显示。 Coil 会将图像加载到内存中,可是若是您须要 500x500 的图像会怎样呢? 从磁盘读取还有更好的「质量」,可是图像已经以 100x100 加载到内存中。 理想状况下,当咱们从磁盘以 500x500 读取图像时,咱们将使用 100x100 图像做为占位符。

这正是 Coil 所作的,而且 Coil 自动为全部 BitmapDrawables 处理此过程。 与 crossfade(true) 搭配使用时,能够建立视觉效果,使图像细节看起来像淡入淡出,相似于渐进式 JPEG

使用要求

  • AndroidX
  • Min SDK 14+
  • Compile SDK: 29+
  • Java 8+

详细内容移步 官方文档

关于我

我是 Fly_with24