- 原標題: Coil vs Picasso vs Glide: Get Ready… Go!
- 原文地址: proandroiddev.com/coil-vs-pic…
- 原文做者:Miguel Ángel Ruiz López
- 這篇文章在 Medium 上到目前爲止得到了 1.4K+ Star,很是好的一篇文章
Coil 做爲圖片加載庫的新秀,和 Glide、Picasso 這些老牌圖片庫相比,它們的優缺點是什麼以及 Coil 將來的展望?先來了解一下什麼是 Coil。android
Coil 是基於 Kotlin 開發的首個圖片加載庫,來自 Instacart 團隊,來看看官網對它的最新的介紹。git
經過這篇文章你將學習到如下內容,將在譯者思考部分會給出相應的答案github
接下來演示中表格中的數字,可能很難理解,可是爲了更好地理解,在最後的部分,會以柱狀圖清晰的展現每一個庫的性能的對比,在譯者思考部分會更深刻的分析這三個圖片加載庫的性能,請耐心多讀幾遍,應該能夠從中學到不少技巧。面試
Coil 做爲圖片庫的新秀,愈來愈受歡迎了,可是爲何會引發這麼多人的關注?在當今主流的圖片加載庫環境中 Coil 是一股清流,它是輕量級的,由於它使用了許多 Android 開發者已經在他們的項目中包含的其餘庫(協程、Okhttp)。算法
當我第一次看到這個庫時,我認爲這些都是很好的改進,可是我很想知道和其餘主流的圖片加載庫相比,這個庫能帶來哪些好處,這篇文章的主要目的是分析一下 Coil 的性能,接下來咱們來對比一下 Coil、 Glide 和 Picasso。編程
爲了弄清楚這些庫的性能如何,咱們分別用它們實現了一個應用程序,這是一個簡單的應用程序,它下載 10 張圖片並以網格佈局顯示它們,以下圖所示。數組
全部圖片都是在同一時間可見的,幾乎是在同一時間被請求的,所以,能夠認爲它們是並行加載。緩存
另外一個須要測試的重要點是第一次加載圖片和從緩存中加載它們所花費的時間,已經進行了屢次測試,覆蓋了上面的場景。安全
咱們開始第一個場景,當緩存爲空時,從網絡中下載圖片。性能優化
Glide
在下面的表中,您能夠看到當緩存爲空時,從網絡中下載圖片所用的時間。注意,這些時間是測試 10 次以後的平均值。
下表展現了加載完整的圖片列表所需的時間,以及平均時間。
Picasso
Picasso 的測試和 Glide 相同,當緩存爲空時,從網絡中下載圖片,測試 10 次左右所用的時間的平均值。
以及加載完整的圖片列表所須要的時間,以及平均時間。
Coil
如今來看一下今天主角 Coil ,和 Picasso、Glide 作相同的測試,當緩存爲空時,從網絡下載 10 次左右所用的時間的平均值。
以及加載完整的圖片列表所需的時間,以及平均時間。
如今開始另一個場景測試,當緩存不爲空時,加載圖片所須要的時間。
Glide
從緩存中加載圖片所用時間,以下表所示。
從緩存中加載完整的圖片列表所需的時間,以及平均時間。
Picasso
測試用例和 Glide 相同,從緩存中加載圖片所用時間,以下表所示。
以及從緩存中加載完整的圖片列表所需的時間,以及平均時間。
Coil
最後咱們來看一下 Coil 如何呢,從緩存中加載圖片所用時間,以下表所示。
一樣的從緩存中加載完整的圖片列表所需的時間,以及平均時間。
爲了更好地理解咱們在測試中獲得的結果,咱們能夠從下面圖表中看到這些數字,反應了從網絡下載每一個圖片時的結果。
Glide 最快 Picasso 和 Coil 幾乎相同。
可是當咱們從緩存中加載的時候,正如你在下面的圖片中看到的,在大多數狀況下,Glide 最快,Coil 其次,Picasso 最慢。
另外一個重要的測試加載完整的圖片列表所花費的時間,這些數字很是重要,由於這是用戶等待看到整個圖片列表的時間。當圖片從網絡加載時,Glide 是最快的,其次是Picasso,Coil是最慢的。
從緩存加載的結果是不一樣的。Glide 和 Coil 幾乎相同,Picasso 是最慢的。
從這些數字中咱們能夠得出幾個結論:
做者從如下場景對 Coil、Glide、Picasso 作了全面的測試。
當緩存爲空時,從網絡中下載圖片的平均時間。
從網絡中下載圖片所用的時間。 結果:Glide 最快 Picasso 和 Coil 幾乎相同。
加載完整的圖片列表所用的時間,以及平均時間。 結果:Glide 是最快的,其次是Picasso,Coil是最慢的。
當緩存不爲空時,從緩存中加載圖片的平均時間。
從緩存中加載圖片所用的時間。 結果:Glide 最快,Coil 其次,Picasso 最慢。
加載完整的圖片列表所用的時間,以及平均時間。 結果:Glide 和 Coil 幾乎相同,Picasso 是最慢的。
圖片加載庫的選擇是咱們應用程序中最重要的部分之一,根據以上結果,若是你的應用程序中沒有大量使用圖片的時候,我認爲使用 Coil 更好,緣由有如下幾點:
若是你的是圖片類型的應用,應用程序中包含了大量的圖片,圖片加載的速度是整個應用的核心指標之一,那麼如今還不適合使用 Coil。
Coil 涵蓋了 Glide、Picasso 等等圖片加載庫所支持的功能,除此以外 Coil 還有一個功能 動態圖片採樣。
更多關於圖片採樣信息能夠訪問 Coil ,這裏簡單的說明一下,假設本地有一個 500x500 的圖片,當從磁盤讀取 500x500 的圖片時,將使用 100x100 的映像做爲佔位符,等待加載完成以後纔會徹底顯示,用官方的一張動圖顯示過程以下。
這種淡入動畫效果,在視覺上體驗很是溫馨,佔位符在主線程上設置,這樣能夠防止在 ImageView 爲空的狀況下出現白色閃爍,接下來讓咱們來看看如何使用 Coil?Coil、Glide 和 Picasso 使用上大比拼?
添加 Coil 依賴
implementation "io.coil-kt:coil:0.11.0"
複製代碼
在 App moudule 下 build.gradle 文件中添加以下代碼
kotlinOptions {
jvmTarget = "1.8"
}
複製代碼
在項目中調用你須要的代碼,這裏彙總了 Coil 全部使用方式
// 將圖片加載到 ImageView 中, 並開啓圖片採樣
// 用到了 Kotlin 的高級特性擴展,調用更加簡單
imageView.load("https://www.example.com/image.jpg"){
crossfade(true)
}
inline fun ImageView.load(
uri: String?,
imageLoader: ImageLoader = Coil.imageLoader(applicationContext),
builder: LoadRequestBuilder.() -> Unit = {}
): RequestDisposable {
return imageLoader.load(context, uri) {
target(this@load)
builder()
}
}
// Coil 支持 Uri,File, String,HttpUrl, Bitmap, Drawable, DrawableId
imageView.load(R.drawable.ic_launcher_background)
imageView.load(File("/path/to/image.jpg"))
imageView.load("content://com.android.externalstorage/image.jpg")
// ......
// Coil 提供了四種轉換: 模糊,圓形剪裁,灰度和圓角
imageView.load("https://www.example.com/image.jpg") {
crossfade(true)
placeholder(R.drawable.ic_launcher_background)
transformations(CircleCropTransformation())
}
// Coil 是一個 object 單例
val imageLoader1 = Coil.imageLoader(applicationContext)
// 能夠建立 或者 調用第三方庫(Koin) 注入本身的實例。
val imageLoader2 = ImageLoader(applicationContext)
// 在某些狀況下,須要遠程下載而後進行回調
var request = LoadRequest.Builder(applicationContext)
.data("https://www.example.com/image.jpg")
.target { drawable ->
// Handle the successful result.
}
.build()
imageLoader2.execute(request)
複製代碼
Coil 基於 Kotlin 而設計,天然也擁有了 Kotlin 的高級函數的特性,使用比 Glide 和 Picasso 要簡單不少。
基本使用
// Coil - 用到了 Kotlin 的高級特性擴展,一行代碼加載圖片
imageView.load(url)
// Glide
Glide.with(context)
.load(url)
.into(imageView)
// Picasso
Picasso.get()
.load(url)
.into(imageView)
複製代碼
後臺線程
// Coil:無阻塞和線程安全
val imageLoader = Coil.imageLoader(context)
val request = GetRequest.Builder(context)
.data(url)
.size(width, height)
.build()
val drawable = imageLoader.execute(request).drawable
// Glide:阻塞當前線程,必定不能從主線程調用
val drawable = Glide.with(context)
.load(url)
.submit(width, height)
.get()
// Picasso:阻塞當前線程,必定不能從主線程調用
val drawable = Picasso.get()
.load(url)
.resize(width, height)
.get()
複製代碼
自動檢測 scaleType
imageView.scaleType = ImageView.ScaleType.FIT_CENTER
// Coil:自動檢測 scaleType
imageView.load(url) {
placeholder(placeholder)
}
// Glide
Glide.with(context)
.load(url)
.placeholder(placeholder)
.fitCenter()
.into(imageView)
// Picasso
Picasso.get()
.load(url)
.placeholder(placeholder)
.fit()
.into(imageView)
複製代碼
如何實現一行代碼交換兩個變量?咱們先來回顧一下 JAVA 的作法
int a = 1;
int b = 2;
// JAVA - 中間變量
int temp = a;
a = b;
b = temp;
System.out.println("a = "+a +" b = "+b); // a = 2 b = 1
// JAVA - 加減運算
a = a + b;
b = a - b;
a = a - b;
System.out.println("a = " + a + " b = " + b); // a = 2 b = 1
// JAVA - 位運算
a = a ^ b;
b = a ^ b;
a = a ^ b;
System.out.println("a = " + a + " b = " + b); // a = 2 b = 1
// Kotlin
a = b.also { b = a }
println("a = ${a} b = ${b}") // a = 2 b = 1
複製代碼
致力於分享一系列 Android 系統源碼、逆向分析、算法、翻譯相關的文章,目前正在翻譯一系列歐美精選文章,請持續關注,除了翻譯還有對每篇歐美文章思考,若是對你有幫助,請幫我點個贊,感謝!!!期待與你一塊兒成長。
因爲 LeetCode 的題庫龐大,每一個分類都能篩選出數百道題,因爲每一個人的精力有限,不可能刷完全部題目,所以我按照經典類型題目去分類、和題目的難易程度去排序
每道題目都會用 Java 和 kotlin 去實現,而且每道題目都有解題思路,若是你同我同樣喜歡算法、LeetCode,能夠關注我 GitHub 上的 LeetCode 題解:Leetcode-Solutions-with-Java-And-Kotlin,一塊兒來學習,期待與你一塊兒成長
正在寫一系列的 Android 10 源碼分析的文章,瞭解系統源碼,不只有助於分析問題,在面試過程當中,對咱們也是很是有幫助的,若是你同我同樣喜歡研究 Android 源碼,能夠關注我 GitHub 上的 Android10-Source-Analysis,文章都會同步到這個倉庫