@author 菠蘿的 ?泡在網(wǎng)上的日子
原文:Glide – How Yelp’s Android App Loads Images
動(dòng)態(tài)加載圖片是很多安卓應(yīng)用的基礎(chǔ)呐伞。在Yelp(美國(guó)最大點(diǎn)評(píng)網(wǎng)站)中,圖片在把消費(fèi)者與商家聯(lián)系起來的過程中至關(guān)重要遂黍。隨著網(wǎng)絡(luò)通信和硬件水平的越發(fā)強(qiáng)大,消費(fèi)者對(duì)于圖片數(shù)量和圖片質(zhì)量的期望日益增長(zhǎng)俊嗽。圖片可以輕易的成為內(nèi)存和網(wǎng)絡(luò)流量的消耗大戶雾家,處理圖片數(shù)據(jù)的下載和管理成為了一個(gè)讓人望而卻步的任務(wù)。我們探索了幾種處理這個(gè)問題的解決辦法绍豁,最終認(rèn)為Glide在性能芯咧,使用方便性,穩(wěn)定性上達(dá)到了相當(dāng)好的平衡竹揍。
Glide最簡(jiǎn)單的使用案例就是從遠(yuǎn)程服務(wù)器或者本地文件系統(tǒng)加載圖片敬飒,把它們放在磁盤與內(nèi)存緩存中,然后加載到view上芬位。它可以用在全市圖片的app中无拗,Glide為包含圖片的滾動(dòng)列表做了盡可能流暢的優(yōu)化。
對(duì)象池
Glide原理的核心是為bitmap維護(hù)一個(gè)對(duì)象池昧碉。對(duì)象池的主要目的是通過減少大對(duì)象的分配以重用來提高性能(至于對(duì)象池的概覽蓝纲,可以查看這個(gè)Android performance pattern 視頻)阴孟。
Dalvik和ART虛擬機(jī)都沒有使用compacting garbage collector,compacting garbage collector是一種模式税迷,這種模式中GC會(huì)遍歷堆,同時(shí)把活躍對(duì)象移到相鄰內(nèi)存區(qū)域锹漱,讓更大的內(nèi)存塊可以用在后續(xù)的分配中箭养。因?yàn)榘沧繘]有這種模式,就可能會(huì)出現(xiàn)被分配的對(duì)象分散在各處哥牍,對(duì)象之間只有很小的內(nèi)存可用毕泌。如果應(yīng)用試圖分配一個(gè)大于鄰近的閑置內(nèi)存塊空間的對(duì)象,就會(huì)導(dǎo)致OutOfMemoryError嗅辣,然后崩潰撼泛,即使總的空余內(nèi)存空間大于對(duì)象的大小。
使用對(duì)象池還可以幫助提高滾動(dòng)的性能澡谭,因?yàn)橹赜胋itmap意味著更少的對(duì)象被創(chuàng)建與回收愿题。垃圾回收會(huì)導(dǎo)致“停止一切(Stop The World)”事件,這個(gè)事件指的是回收器執(zhí)行期間蛙奖,所有線程(包括UI線程)都會(huì)暫停潘酗。這個(gè)時(shí)候,圖像幀無法被渲染同時(shí)UI可能會(huì)停滯雁仲,這在滾動(dòng)期間尤其明顯仔夺。
Glide的使用
Glide使用起來很簡(jiǎn)單,而且不需要任何特別的配置就自動(dòng)包含了bitmap pooling 攒砖。
DrawableRequestBuilder requestBuilder = Glide.with(context).load(imageUrl);
requestBuilder.into(imageView);
這就是加載一張圖片的全部要求缸兔。就像安卓中的很多地方一樣,with() 方法中的context到底是哪種類型是不清楚的吹艇。有一點(diǎn)很重要需要記住惰蜜,就是傳入的context類型影響到Glide加載圖片的優(yōu)化程度,Glide可以監(jiān)視activity的生命周期掐暮,在activity銷毀的時(shí)候自動(dòng)取消等待中的請(qǐng)求蝎抽。但是如果你使用Application?context,你就失去了這種優(yōu)化效果路克。
譯者注:其實(shí)以上的代碼是一種比較規(guī)范的寫法樟结,我們更熟悉的寫法是:
Glide.with(context).load("http://inthecheesefactory.com/uploads/source/glidepicasso/cover.jpg").into(ivImg);
優(yōu)化特性
類似的是,如果相關(guān)的item已經(jīng)滾出了屏幕的范圍精算,Glide會(huì)自動(dòng)取消列表中的懸著的圖片請(qǐng)求 瓢宦。因?yàn)榻^大多數(shù)開發(fā)者都會(huì)在adapter中利用view的回收,Glide做到這點(diǎn)是通過在ImageView上設(shè)置一個(gè)tag灰羽,在加載另外一張圖片之前檢查這個(gè)tag驮履,如果存在就取消第一次請(qǐng)求鱼辙。
Glide提供了幾個(gè)讓你感覺圖片加載速度變快的特性。第一個(gè)就是在圖片顯示在屏幕上之前就預(yù)先取出圖片玫镐。它提供了一個(gè)ListPreloader類倒戏, 它被應(yīng)該事先取出的item數(shù)目實(shí)例化。然后通過setOnScrollListener(OnScrollListener).被傳遞給ListView恐似。你想在ListView之外也能預(yù)先取出圖片嗎杜跷?沒問題,使用前面的builder對(duì)象就可以了矫夷,只需調(diào)用builder.downloadOnly()葛闷。
downloadOnly見:https://github.com/bumptech/glide/wiki/Loading-and-Caching-on-Background-Threads。
我們發(fā)現(xiàn)了Glide提供的可以大大提高性能双藕,穩(wěn)定性的功能淑趾,以及安卓圖片加載領(lǐng)域的一些設(shè)計(jì)哲學(xué)。這些特性和優(yōu)化確實(shí)可以很好的將圖片加載的體驗(yàn)變成一種享受忧陪。