【奇淫巧技】新的圖片加載庫?基於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

相關文章
相關標籤/搜索