圖片加載和顯示在android開發(fā)中是最常見的需求之一,因此圖片加載和顯示這個問題處理的好壞會直接影響到我們產(chǎn)品的用戶體驗弱恒,尤其是在移動設(shè)備的硬件和網(wǎng)絡(luò)都比較受限的條件下。鑒于此糖声,一些知名的廠商和開發(fā)者貢獻并開源了他們在這一塊的所做的探索和努力斤彼,于是就有了目前android開發(fā)中最常見的四大圖片加載框架:Universal Image Loader,Picasso蘸泻,Glide和Fresco琉苇。他們都能很好的幫助我們完成圖片加載這項復(fù)雜的任務(wù),同時又有著各自的優(yōu)勢和不足悦施。那么并扇,作為開發(fā)者的我們,如何去選擇其中一個或幾個來幫助我們產(chǎn)品實現(xiàn)并優(yōu)化圖片加載顯示這一塊的功能抡诞,就需要我們弄清楚他們的原理穷蛹,以及他們之間的區(qū)別。
Universal Image Loader
Universal Image Loader是最早出現(xiàn)的一個知名圖片加載顯示框架昼汗,雖然現(xiàn)在已經(jīng)停止維護了肴熏,但是仍然被很多的開發(fā)者所使用。并且顷窒,后續(xù)出現(xiàn)的Picasso蛙吏,Glide和Fresco也都或多或少借鑒了它的設(shè)計思想和理念。首先鞋吉,我們來看一下他的總體設(shè)計:
總體來說鸦做,Universal Image Loader簡單清晰的分層結(jié)構(gòu)設(shè)計,使得其具有以下優(yōu)點:
- 支持View在滾動過程中暫停圖片加載谓着。在ListView滑動過程中可以節(jié)省不必要的性能開銷和內(nèi)存開銷
- 可以對多個模塊進行單獨配置泼诱,并且配置上也很方便靈活。例如線程池赊锚,內(nèi)存緩存策略治筒,硬盤緩存策略,圖片顯示選項等
- 支持多級緩存以及多種緩存算法舷蒲,可以根據(jù)使用場景選擇適合的緩存策略
-
可以根據(jù)ImageView的大小對Bitmap進行裁剪矢炼,減少Bitmap占用過多的內(nèi)存
其中它的緩存設(shè)計也是我們最常見的一種三級緩存設(shè)計,后面的三種圖片加載框架都采用了類似的設(shè)計阿纤,即內(nèi)存緩存句灌,磁盤緩存和網(wǎng)絡(luò)緩存。具體流程如下:
三級緩存設(shè)計不僅在性能上可以降低Cpu的處理開銷,在內(nèi)存占用上也可以達到較好的控制避免OOM的發(fā)生胰锌,從而保證良好的圖片加載體驗骗绕。但是在某些場景,比如在圖片較多的應(yīng)用资昧,尤其是長列表視圖中酬土,當(dāng)用戶快速滾動視圖時,由于圖片較大較多格带,內(nèi)存緩存大小的限制會導(dǎo)致頻繁的Bitmap回收撤缴,進而導(dǎo)致內(nèi)存的緩存命中率嚴重下降最終影響到圖片的加載效率。
Picasso
Picasso是鼎鼎有名的Square公司的一個開源項目叽唱,該公司同時開源了許多知名的項目屈呕,比如Okhttp,Retrofit棺亭,Otto等虎眨。Picasso繼承了Okhttp的鏈式調(diào)用風(fēng)格,使得它使用起來非常簡單和方便镶摘,并且它的設(shè)計和實現(xiàn)也很輕量簡單嗽桩,使得整個庫的接口數(shù)量和體積都很小,因此被很多開發(fā)者使用在項目中凄敢。下面我們來看一下Picasso的總體設(shè)計:
總體來說碌冶,Picasso同樣具有簡單清晰的的分層結(jié)構(gòu)設(shè)計,其優(yōu)點如下:
- 自帶統(tǒng)計監(jiān)控涝缝,如緩存命中率种樱,內(nèi)存使用大小,節(jié)省的流量等
- 支持優(yōu)先級處理俊卤,每次任務(wù)調(diào)度前會選擇優(yōu)先級高的任務(wù)
- 支持飛行模式,并發(fā)線程數(shù)根據(jù)網(wǎng)絡(luò)類型變化
-
其并沒有自己設(shè)計一套磁盤緩存害幅,而是通過通過Okhttp網(wǎng)絡(luò)請求庫去實現(xiàn)消恍,這樣的好處是可以通過Response Header中的cache-control和expired靈活的控制本地緩存
接下來我們看下其緩存設(shè)計流程:
Picasso的緩存設(shè)計和Universal Image Loader類似,但是其本地緩存有所不同以现,Picasso是通過服務(wù)器來實現(xiàn)的本地緩存并且都是原圖狠怨,因此如果能根據(jù)圖片尺寸來控制緩存圖片的大小可以進一步降低本地儲存的空間和圖片處理的開銷。
Glide
Glide是Google的一位員工實現(xiàn)的一個圖片加載庫邑遏,同時也是被Google官方推薦的佣赖。它在Picasso的基礎(chǔ)上做了許多優(yōu)化和改進,使得其在圖片加載的性能上要比Picasso好记盒,并且繼承了Picasso的許多優(yōu)良特性憎蛤,比如鏈式調(diào)用,靈活配置等,所以也被很多開發(fā)者所使用俩檬。下面我們看下Glide的總體設(shè)計:
總體來說萎胰,Glide同樣具有簡單清晰的的分層結(jié)構(gòu)設(shè)計,相比Picasso其增加了如下功能:
- 支持Gif棚辽,Webp以及視頻文件的解碼
- 支持縮略圖
- activity生命周期綁定
-
支持加載動畫
接下來我們看下Glide的緩存設(shè)計流程:
相比Picasso技竟,Glide在緩存設(shè)計上進行了很多優(yōu)化,比如屈藐,依據(jù)Activity的生命周期按使用場景對內(nèi)存緩存進行了進一步的劃分榔组,做到了及時釋放不必要的內(nèi)存的同時也避免了當(dāng)前或者即將要使用的緩存不會被回收而導(dǎo)致重新加載的情況。同時联逻,利用了android4.4以上系統(tǒng)支持Bitmap復(fù)用的特性搓扯,進一步降低了Bitmap的創(chuàng)建開銷。
Fresco
Fresco是Facebook公司開發(fā)的一個圖片加載框架遣妥。和Glide類似擅编,其功能也很強大,尤其是在圖片緩存這一塊更是使用了一些黑科技來提高效率箫踩。下面我們來看一下Fresco的總體設(shè)計流程:
總體來說Fesco的主要目標(biāo)是盡可能的提高圖片加載的效率爱态,使得其設(shè)計比前面三種要復(fù)雜得多。下面來說下它的優(yōu)點:
- 4.4以及之前的系統(tǒng)上利用了匿名共享內(nèi)存境钟,使得app可以使用比正常狀態(tài)下更多的內(nèi)存锦担;
- 漸進式加載jpeg圖片,支持圖片從模糊到清晰加載慨削;
- 圖片可以以任意的中心點顯示在 ImageView上洞渔;
- 支持gif的顯示
下面我們看下其具體的緩存實現(xiàn)流程:
可以看出,fresco針對圖片的解碼環(huán)節(jié)做了優(yōu)化缚态,我們知道解碼過程也是比較占用CPU資源的磁椒,這一點上其加載效率比其他3個就要好。此外玫芦,對于內(nèi)存的占用浆熔,fresco也是做到了極致,除了使用Ashmem的黑科技外桥帆,還采用了類似GC的引用計數(shù)機制医增,通過對圖片對象的引起計數(shù),使得不再使用的圖片對象可以更早的被回收以便降低內(nèi)存開銷老虫。
總結(jié)
Universal Image Loader是早期比較有代表性的圖片加載庫叶骨,雖然目前已經(jīng)停止維護,不再推薦使用祈匙,但是其架構(gòu)設(shè)計和實現(xiàn)依然值得借鑒忽刽。Picasso的設(shè)計充分體現(xiàn)了Square公司在架構(gòu)設(shè)計上一貫的簡潔易用風(fēng)格(鏈式調(diào)用)。Glide充分吸收了Picasso的優(yōu)點,并在此基礎(chǔ)上做了大量的優(yōu)化和改進缔恳。Fresco 可以說是綜合了之前圖片加載庫的優(yōu)點并將性能優(yōu)化到極致宝剖,但它的包很大,用法比較復(fù)雜歉甚,API不夠簡潔万细,所以, Fresco 在圖片較多的應(yīng)用中更能凸顯其價值纸泄,如果應(yīng)用沒有太多圖片需求赖钞,還是不推薦使用 Fresco,Glide基本就能滿足需求聘裁。