andrid四大圖片載入框架對比分析
圖片載入和顯示在android開發中是最常見的需求之一,因此圖片載入和顯示這個問題處理的好壞會直接影響到我們產品的使用者體驗,尤其是在移動裝置的硬體和網路都比較受限的條件下。鑑於此,一些知名的廠商和開發者貢獻並開源了他們在這一塊的所做的探索和努力,於是就有了目前android開發中最常見的四大圖片載入框架:Universal Image Loader,Picasso,Glide和Fresco。他們都能很好的幫助我們完成圖片載入這項複雜的任務,同時又有著各自的優勢和不足。那麼,作為開發者的我們,如何去選擇其中一個或幾個來幫助我們產品實現並優化圖片載入顯示這一塊的功能,就需要我們弄清楚他們的原理,以及他們之間的區別。
Universal Image Loader
Universal Image Loader是最早出現的一個知名圖片載入顯示框架,雖然現在已經停止維護了,但是仍然被很多的開發者所使用。並且,後續出現的Picasso,Glide和Fresco也都或多或少借鑑了它的設計思想和理念。首先,我們來看一下他的總體設計:

總體來說,Universal Image Loader簡單清晰的分層結構設計,使得其具有以下優點:
- 支援View在滾動過程中暫停圖片載入。在ListView滑動過程中可以節省不必要的效能開銷和記憶體開銷
- 可以對多個模組進行單獨配置,並且配置上也很方便靈活。例如執行緒池,記憶體快取策略,硬碟快取策略,圖片顯示選項等
- 支援多級快取以及多種快取演算法,可以根據使用場景選擇適合的快取策略
-
可以根據ImageView的大小對Bitmap進行裁剪,減少Bitmap佔用過多的記憶體
其中它的快取設計也是我們最常見的一種三級快取設計,後面的三種圖片載入框架都採用了類似的設計,即記憶體快取,磁碟快取和網路快取。具體流程如下:
三級快取設計不僅在效能上可以降低Cpu的處理開銷,在記憶體佔用上也可以達到較好的控制避免OOM的發生,從而保證良好的圖片載入體驗。但是在某些場景,比如在圖片較多的應用,尤其是長列表檢視中,當用戶快速滾動檢視時,由於圖片較大較多,記憶體快取大小的限制會導致頻繁的Bitmap回收,進而導致記憶體的快取命中率嚴重下降最終影響到圖片的載入效率。
Picasso
Picasso是鼎鼎有名的Square公司的一個開源專案,該公司同時開源了許多知名的專案,比如Okhttp,Retrofit,Otto等。Picasso繼承了Okhttp的鏈式呼叫風格,使得它使用起來非常簡單和方便,並且它的設計和實現也很輕量簡單,使得整個庫的介面數量和體積都很小,因此被很多開發者使用在專案中。下面我們來看一下Picasso的總體設計:

總體來說,Picasso同樣具有簡單清晰的的分層結構設計,其優點如下:
- 自帶統計監控,如快取命中率,記憶體使用大小,節省的流量等
- 支援優先順序處理,每次任務排程前會選擇優先順序高的任務
- 支援飛航模式,併發執行緒數根據網路型別變化
-
其並沒有自己設計一套磁碟快取,而是通過通過Okhttp網路請求庫去實現,這樣的好處是可以通過Response Header中的cache-control和expired靈活的控制本地快取
接下來我們看下其快取設計流程:
Picasso的快取設計和Universal Image Loader類似,但是其本地快取有所不同,Picasso是通過伺服器來實現的本地快取並且都是原圖,因此如果能根據圖片尺寸來控制快取圖片的大小可以進一步降低本地儲存的空間和圖片處理的開銷。
Glide
Glide是Google的一位員工實現的一個圖片載入庫,同時也是被Google官方推薦的。它在Picasso的基礎上做了許多優化和改進,使得其在圖片載入的效能上要比Picasso好,並且繼承了Picasso的許多優良特性,比如鏈式呼叫,靈活配置等,所以也被很多開發者所使用。下面我們看下Glide的總體設計:

總體來說,Glide同樣具有簡單清晰的的分層結構設計,相比Picasso其增加了如下功能:
- 支援Gif,Webp以及視訊檔案的解碼
- 支援縮圖
- activity生命週期繫結
-
支援載入動畫
接下來我們看下Glide的快取設計流程:
相比Picasso,Glide在快取設計上進行了很多優化,比如,依據Activity的生命週期按使用場景對記憶體快取進行了進一步的劃分,做到了及時釋放不必要的記憶體的同時也避免了當前或者即將要使用的快取不會被回收而導致重新載入的情況。同時,利用了android4.4以上系統支援Bitmap複用的特性,進一步降低了Bitmap的建立開銷。
Fresco
Fresco是Facebook公司開發的一個圖片載入框架。和Glide類似,其功能也很強大,尤其是在圖片快取這一塊更是使用了一些黑科技來提高效率。下面我們來看一下Fresco的總體設計流程:

總體來說Fesco的主要目標是儘可能的提高圖片載入的效率,使得其設計比前面三種要複雜得多。下面來說下它的優點:
- 4.4以及之前的系統上利用了匿名共享記憶體,使得app可以使用比正常狀態下更多的記憶體;
- 漸進式載入jpeg圖片,支援圖片從模糊到清晰載入;
- 圖片可以以任意的中心點顯示在 ImageView上;
- 支援gif的顯示
下面我們看下其具體的快取實現流程:

可以看出,fresco針對圖片的解碼環節做了優化,我們知道解碼過程也是比較佔用CPU資源的,這一點上其載入效率比其他3個就要好。此外,對於記憶體的佔用,fresco也是做到了極致,除了使用Ashmem的黑科技外,還採用了類似GC的引用計數機制,通過對圖片物件的引起計數,使得不再使用的圖片物件可以更早的被回收以便降低記憶體開銷。
總結
Universal Image Loader是早期比較有代表性的圖片載入庫,雖然目前已經停止維護,不再推薦使用,但是其架構設計和實現依然值得借鑑。Picasso的設計充分體現了Square公司在架構設計上一貫的簡潔易用風格(鏈式呼叫)。Glide充分吸收了Picasso的優點,並在此基礎上做了大量的優化和改進。Fresco 可以說是綜合了之前圖片載入庫的優點並將效能優化到極致,但它的包很大,用法比較複雜,API不夠簡潔,所以, Fresco 在圖片較多的應用中更能凸顯其價值,如果應用沒有太多圖片需求,還是不推薦使用 Fresco,Glide基本就能滿足需求。