Android緩存分為內(nèi)存緩存和磁盤緩存。
內(nèi)存緩存(LruCache)
在早期的 Android 2.x 時(shí)代,常用的緩存方式是軟引用(SoftReference)和弱引用(WeakReference),如大部分的使用方式:HashMap<String url, SoftReference<Drawable>> imageCache;這種形式。從Android 2.3(Level 9)開始,垃圾回收器更傾向于回收 SoftReference 或 WeakReference 對(duì)象,這使得 SoftReference和 WeakReference 變得不是那么實(shí)用有效。
同時(shí),到了Android 3.0(Level 11)之后,圖片數(shù)據(jù)Bitmap被放置到了內(nèi)存的堆區(qū)域,而堆區(qū)域的內(nèi)存是由GC管理的,開發(fā)者也就不需要進(jìn)行圖片資源的釋放工作,但這也使得圖片數(shù)據(jù)的釋放無法預(yù)知,增加了造成OOM的可能。
因此,在Android3.1以后,Android推出了LruCache這個(gè)內(nèi)存緩存類,LruCache中的對(duì)象是強(qiáng)引用的。
LruCache 是 Android 3.1 開始提供的一種基于內(nèi)存的緩存框架,LRU 是 Least Recently Used 的縮寫,即最近最少使用。當(dāng)一塊內(nèi)存最近很少使用的時(shí)候就會(huì)被從緩存中移除。它內(nèi)部采用一個(gè) LinkedHashMap 以強(qiáng)引用的方式存儲(chǔ)外界的緩存對(duì)象,其提供了get和put方法來完成緩存的獲取和添加操作,當(dāng)緩存滿時(shí),LruCache 會(huì)移除較早的緩存對(duì)象,然后再添加新的緩存對(duì)象。
LruCache 是線程安全的。
-
使用 LruCache
SDK 自帶,可直接使用。
注意:LruCache 從 Android 3.1 開始已經(jīng)作為 android 源碼的一部分維護(hù)在 android 系統(tǒng)中,為了兼容以前的版本, android 的 support-v4 包也提供了 LruCache 的維護(hù)。如果 App 需要兼容到 android 3.1 之前的版本就需要使用 support-v4 包中的 LruCache,如果不需要兼容到 android 3.1 則直接使用android 源碼中的 LruCache 即可。
-
LruCache 常用 API
方法名 釋義 LruCache(int maxSize) 實(shí)例化 Lru,需要傳入緩存的最大值,這個(gè)最大值可以是個(gè)數(shù),比如對(duì)象的個(gè)數(shù),也可以是內(nèi)存的大小 resize(int maxSize) 重置最大存儲(chǔ)空間 get(K key) 通過 key 返回相應(yīng)的 item,或者創(chuàng)建返回相應(yīng)的 item。相應(yīng)的item會(huì)移動(dòng)到隊(duì)列的頭部,如果 item 的value沒有被 cache 或者不能被創(chuàng)建,則返回 null。 put(K key, V value) 創(chuàng)建 cache 項(xiàng),并將創(chuàng)建的項(xiàng)放到隊(duì)列的頭部 trimToSize(int maxSize) 清空 cache 空間 remove(K key) 刪除 key 相應(yīng)的 cache 項(xiàng),返回相應(yīng)的 value create(K key 當(dāng)某 Item 丟失時(shí)會(huì)調(diào)用到,返回計(jì)算的相應(yīng)的 value 或者 null sizeOf(K key, V value) 這個(gè)方法要特別注意,跟我們實(shí)例化 LruCache 的 maxSize 要呼應(yīng),怎么做到呼應(yīng)呢,比如 maxSize 的大小為緩存的個(gè)數(shù),這里就是 return 1就 ok,如果是內(nèi)存的大小,如果5 M,這個(gè)就不能是個(gè)數(shù)了,就需要覆蓋這個(gè)方法,返回每個(gè)緩存 value 的size大小,如果是 Bitmap,這應(yīng)該是 bitmap.getByteCount(); evictAll() 清空 cache evictionCount() 返回被回收的數(shù)量 snapshot() 返回當(dāng)前cache的副本,從最近最少訪問到最多訪問
磁盤緩存(DiskLruCache)
DiskLruCache 不同于 LruCache,LruCache 是將數(shù)據(jù)緩存到內(nèi)存中去,而 DiskLruCache 是外部緩存,例如可以將網(wǎng)絡(luò)下載的圖片永久的緩存到手機(jī)外部存儲(chǔ)中去,并可以將緩存數(shù)據(jù)取出來使用。
DiskLruCache 不是 Android 自帶類,是大神 JakeWharton 開源的,但是得到了官方推薦。DiskLruCache 沒有編寫到 SDK 中,如需使用可直接 copy 這個(gè)類到項(xiàng)目中去。
-
使用 DiskLruCache
-
直接代碼中引用
compile 'com.jakewharton:disklrucache:2.0.2'
DiskLruCache 常用 API
方法名 | 釋義 |
---|---|
DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize) | DiskLruCache 實(shí)例化方法。作用是打開一個(gè)緩存目錄,如果沒有則首先創(chuàng)建它。directory:指定數(shù)據(jù)緩存地址;appVersion:APP版本號(hào),當(dāng)版本號(hào)改變時(shí),緩存數(shù)據(jù)會(huì)被清除 ;valueCount:同一個(gè)key可以對(duì)應(yīng)多少文件 ;maxSize:最大可以緩存的數(shù)據(jù)量。 |
Editor edit(String key) | 通過key可以獲得一個(gè)DiskLruCache.Editor,通過Editor可以得到一個(gè)輸出流,進(jìn)而緩存到本地存儲(chǔ)上。 |
void flush() | 強(qiáng)制緩沖文件保存到文件系統(tǒng) |
Snapshot get(String key) | 通過key值來獲得一個(gè)Snapshot,如果Snapshot存在,則移動(dòng)到LRU隊(duì)列的頭部來,通過Snapshot可以得到一個(gè)輸入流InputStream |
long size() | 緩存數(shù)據(jù)的大小,單位是byte |
boolean remove(String key) | 根據(jù)key值來刪除對(duì)應(yīng)的數(shù)據(jù),如果該數(shù)據(jù)正在被編輯,則不能刪除 |
void delete() | 關(guān)閉緩存并且刪除目錄下所有的緩存數(shù)據(jù),即使有的數(shù)據(jù)不是由DiskLruCache 緩存到本目錄的 |
void close() | 關(guān)閉DiskLruCache,緩存數(shù)據(jù)會(huì)保留在外存中 |
boolean isClosed() | 判斷DiskLruCache是否關(guān)閉,返回true表示已關(guān)閉 |
File getDirectory() | 緩存數(shù)據(jù)的目錄 |