Android開發中一定會遇到圖片加載,圖片緩存的問題。Universal-Image-Loader是我遇到過的比較不錯的一個開源框架,是國外一個大牛寫的,據說現在作者已經不維護了,下面就源碼來學習一下,歡迎交流!
首先看源碼目錄結構
從目錄中可見,Universal-Image-Loader(后面用UIL表示)提供了兩種緩存方式,內存和磁盤。再來介紹一下UIL的緩存流程。
還是一張圖。
①UI:請求數據,使用唯一的Key值索引Memory Cache中的Bitmap。
②內存緩存:緩存搜索,如果能找到Key值對應的Bitmap,則返回數據。否則執行第三步。
③硬盤存儲:使用唯一Key值對應的文件名,檢索SDCard上的文件。
④如果有對應文件,使用BitmapFactory.decode*方法,解碼Bitmap并返回數據,同時將數據寫入緩存。如果沒有對應文件,執行第五步。
⑤下載圖片:啟動異步線程,從數據源下載數據(Web)。
⑥若下載成功,將數據同時寫入硬盤和緩存,并將Bitmap顯示在UI中。
上面片段摘自其他技術貼,應該都是淺顯易懂。不過我來追加補充了解一下,加深認識。
首先是1的Key值,從代碼中看Key值如何生成。
String memoryCacheKey = MemoryCacheUtils.generateKey(uri, targetSize);
可見,memoryCacheKey和圖片url本身以及要顯示的目標大小作為唯一key。就是說就算同一張圖片,只要顯示為不同尺寸,也不是用的
同一個bitmap。
另外3中的從代碼查看是直接用文件名檢索而不是先通過唯一key。
聊完基本業務流程,就來談談UIL都提供了哪些緩存算法。再來看一張圖
從圖片可以看出,UIL提供的內存緩存算法比較豐富,有8種,磁盤緩存則只有2種。下面稍微介紹一下各自算法的大致意思。
1、FIFOlimitedMemoryCache
先進先出的緩存策略,當超過設定值,先刪除最先加入緩存的bitmap。
2、FuzzyKeyMemoryCache
這個是內部使用,用于比較bitmap是否存在,有則移除。
3、LimitedMemeryCache
使用強引用和弱引用結合的緩存策略,cacheSize以內的為強引用,cacheSize以外的為弱引用。
4、LargestLimitedMemeryCache
當超過緩存限定值,先刪除最大的bitmap對象。
5、LimitedAgeMemoryCache
當 bitmap加入緩存中的時間超過我們設定的值,將其刪除。
6、LRULMemoryCache
使用的LRU算法,當有需要時最近最少使用bitmap從緩存中刪除。
7、LRULimitedMemoryCache
這個也是使用的LRU算法,和LruMemoryCache不同的是,他緩存加入了弱引用。cacheSize以內的為強引用,cacheSize以外的為弱引用。
8、WeakMemoryCache
這個算法只使用了弱引用來作為緩存策略。
接下來就是磁盤緩存
imitedAgeDiscCache
設定文件存活的最長時間,當超過這個值,就刪除該文件。
UnlimitedDiscCache
這個緩存類沒有任何的限制。
介紹完上面的緩存算法之后,大家是否都看到了,強引用、軟引用、弱引用等概念。現在就這三個再介紹介紹。
1.強引用
以前我們使用的大部分引用實際上都是強引用,這是使用最普遍的引用。如果一個對象具有強引用,那就類似于必不可少的生活用品,垃圾回收器絕不會回收它。當內存空間不足,Java虛擬機寧愿拋出OutOfMemoryError錯誤,使程序異常終止,也不會靠隨意回收具有強引用的對象來解決內存不足問題。
2.軟引用(SoftReference)
如果一個對象只具有軟引用,那就類似于可有可物的生活用品。如果內存空間足夠,垃圾回收器就不會回收它,如果內存空間不足了,就會回收這些對象的內存。只要垃圾回收器沒有回收它,該對象就可以被程序使用。軟引用可用來實現內存敏感的高速緩存。
軟引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果軟引用所引用的對象被垃圾回收,JAVA虛擬機就會把這個軟引用加入到與之關聯的引用隊列中。
3.弱引用(WeakReference)
如果一個對象只具有弱引用,那就類似于可有可物的生活用品。弱引用與軟引用的區別在于:只具有弱引用的對象擁有更短暫的生命周期。在垃圾回收器線程掃描它所管轄的內存區域的過程中,一旦發現了只具有弱引用的對象,不管當前內存空間足夠與否,都會回收它的內存。不過,由于垃圾回收器是一個優先級很低的線程, 因此不一定會很快發現那些只具有弱引用的對象。
弱引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果弱引用所引用的對象被垃圾回收,Java虛擬機就會把這個弱引用加入到與之關聯的引用隊列中。
其實UIL這個框架的代碼中可以看到很多Java的一些編程思想,設計模式等。但出于時間考慮,先寫這些,后面有時間繼續補充。