Yelp app是如何使用Glide優化圖片載入的

jcodecraeer發表於2015-07-31

動態載入圖片是很多安卓應用的基礎。在Yelp(美國最大點評網站)中,圖片在把消費者與商家聯絡起來的過程中至關重要。隨著網路通訊和硬體水平的越發強大,消費者對於圖片數量和圖片質量的期望日益增長。圖片可以輕易的成為記憶體和網路流量的消耗大戶,處理圖片資料的下載和管理成為了一個讓人望而卻步的任務。我們探索了幾種處理這個問題的解決辦法,最終認為Glide在效能,使用方便性,穩定性上達到了相當好的平衡。

Glide最簡單的使用案例就是從遠端伺服器或者本地檔案系統載入圖片,把它們放在磁碟與記憶體快取中,然後載入到view上。它可以用在全市圖片的app中,Glide為包含圖片的滾動列表做了儘可能流暢的優化。

物件池

Glide原理的核心是為bitmap維護一個物件池。物件池的主要目的是通過減少大物件的分配以重用來提高效能(至於物件池的概覽,可以檢視 這個Android performance pattern 視訊)。

Dalvik和ART虛擬機器都沒有使用compacting garbage collector,compacting garbage collector是一種模式,這種模式中GC會遍歷堆,同時把活躍物件移到相鄰記憶體區域,讓更大的記憶體塊可以用在後續的分配中。因為安卓沒有這種模式,就可能會出現被分配的物件分散在各處,物件之間只有很小的記憶體可用。如果應用試圖分配一個大於鄰近的閒置記憶體塊空間的物件,就會導致OutOfMemoryError,然後崩潰,即使總的空餘記憶體空間大於物件的大小。

使用物件池還可以幫助提高滾動的效能,因為重用bitmap意味著更少的物件被建立與回收。垃圾回收會導致“停止一切(Stop The World)”事件,這個事件指的是回收器執行期間,所有執行緒(包括UI執行緒)都會暫停。這個時候,影像幀無法被渲染同時UI可能會停滯,這在滾動期間尤其明顯。

Yelp app是如何使用Glide優化圖片載入的

Glide的使用

Glide使用起來很簡單,而且不需要任何特別的配置就自動包含了bitmap pooling 。

DrawableRequestBuilder requestBuilder = Glide.with(context).load(imageUrl);
requestBuilder.into(imageView);

這就是載入一張圖片的全部要求。就像安卓中的很多地方一樣,with() 方法中的context到底是哪種型別是不清楚的。有一點很重要需要記住,就是傳入的context型別影響到Glide載入圖片的優化程度,Glide可以監視activity的生命週期,在activity銷燬的時候自動取消等待中的請求。但是如果你使用Application context,你就失去了這種優化效果。

譯者注:其實以上的程式碼是一種比較規範的寫法,我們更熟悉的寫法是:

Glide.with(context)
    .load("http://inthecheesefactory.com/uploads/source/glidepicasso/cover.jpg")
    .into(ivImg);

優化特性

類似的是,如果相關的item已經滾出了螢幕的範圍,Glide會自動取消列表中的懸著的圖片請求 。因為絕大多數開發者都會在adapter中利用view的回收,Glide做到這點是通過在ImageView上設定一個tag,在載入另外一張圖片之前檢查這個tag,如果存在就取消第一次請求。

Glide提供了幾個讓你感覺圖片載入速度變快的特性。第一個就是在圖片顯示在螢幕上之前就預先取出圖片。它提供了一個ListPreloader類, 它被應該事先取出的item數目例項化。然後通過setOnScrollListener(OnScrollListener).被傳遞給ListView。你想在ListView之外也能預先取出圖片嗎?沒問題,使用前面的builder物件就可以了,只需呼叫builder.downloadOnly()。

downloadOnly見:https://github.com/bumptech/glide/wiki/Loading-and-Caching-on-Background-Threads 。

我們發現了Glide提供的可以大大提高效能,穩定性的功能,以及安卓圖片載入領域的一些設計哲學。這些特性和優化確實可以很好的將圖片載入的體驗變成一種享受。

相關文章