1、什么是緩存?
緩存技術(shù)原理就是把用戶(hù)訪問(wèn)的所有對(duì)象看作一個(gè)全集,經(jīng)過(guò)算法標(biāo)記哪些是用戶(hù)經(jīng)常訪問(wèn)的對(duì)象,把這些對(duì)象放到一個(gè)集合里,這個(gè)集合是全集一個(gè)子集,下一次用戶(hù)再訪問(wèn)的時(shí)候會(huì)先從這個(gè)子集集合中查找用戶(hù)要訪問(wèn)的對(duì)象如果找到就直接返回這個(gè)對(duì)象,如果沒(méi)有找到則再去全集中查找。當(dāng)然了我這里說(shuō)的只是原理性的東西,緩存是有很多算法的,并且有的不止一級(jí)緩存,這里就不過(guò)多講了。
2、為什么要用到緩存?
有緩存的話可以不必每次從源地址讀取文件,既節(jié)省了時(shí)間也節(jié)省了流量。尤其是手機(jī)設(shè)備,頻繁的訪問(wèn)網(wǎng)絡(luò)資源會(huì)消耗很多用戶(hù)的流量和電量,這是用戶(hù)不能忍受的,所以無(wú)論從哪個(gè)方面考慮應(yīng)用程序都必須加上緩存。
3、Android中的圖片緩存有哪些?各有什么特點(diǎn)?
Android設(shè)備的圖片緩存分兩種,一種是內(nèi)存緩存,圖片緩存在設(shè)備的內(nèi)存中,一種是外部緩存,圖片緩存在磁盤(pán)上,磁盤(pán)可以是內(nèi)部的存儲(chǔ)空間也可以是外部的sd卡。這兩種緩存各有各的優(yōu)點(diǎn),內(nèi)存緩存優(yōu)點(diǎn)是快,缺點(diǎn)是因?yàn)橐彩亲x取到內(nèi)存中所以也會(huì)消耗內(nèi)存,所以不能太大,用的時(shí)候要考慮分配的空間,還有一個(gè)缺點(diǎn)是應(yīng)用重啟后就會(huì)消失。外部緩存的優(yōu)點(diǎn)是可以長(zhǎng)久保存大量的數(shù)據(jù)(相比較內(nèi)存緩存而言),缺點(diǎn)就是慢。
4、內(nèi)存緩存
在Android中官網(wǎng)推薦使用LruCache作為內(nèi)存緩存,LruCache實(shí)際上就是一個(gè)LinkedHashMap( 補(bǔ)充知識(shí):LinkedHashMap是一個(gè)雙向循環(huán)列表,不支持線程安全,LruCache對(duì)它進(jìn)行了封裝添加了線程安全操作),里面保存了一定數(shù)量的對(duì)象強(qiáng)引用,每次添加的新對(duì)象都是在鏈表的頭,當(dāng)分配的空間用完的時(shí)候會(huì)把末尾的對(duì)象移除,移除的對(duì)象就可以被gc回收了。這里需要注意一下LruCache的容量,這個(gè)容量既不能太大,會(huì)造成OOM,又不能太小,起不到緩存的作用。
5、Google官網(wǎng)給出意見(jiàn)作為參考:
分配LruCache大小的時(shí)候考慮你的應(yīng)用剩余內(nèi)存有多大;
一次屏幕顯示多少?gòu)垐D片,有多少?gòu)垐D片是緩存起來(lái)準(zhǔn)備顯示的;
考慮你的手機(jī)分辨率和尺寸, 緩存相同的圖片個(gè)數(shù),dpi越大的手機(jī)需要的內(nèi)存就會(huì)越大;
圖片分辨率和像素質(zhì)量也決定了占用內(nèi)存的大?。?/p>
圖片訪問(wèn)的頻繁程度是多少,是不是有一些圖片是經(jīng)常訪問(wèn)的?如果存在你可以考慮用多個(gè)·LruCache來(lái)做緩存,按照訪問(wèn)的頻率度分配到不同的LruCache中;
如何平衡一下圖片質(zhì)量和數(shù)量,有些時(shí)候可以考慮緩存低分辨率的圖片,用到的時(shí)候再在后臺(tái)請(qǐng)求更高質(zhì)量的圖片;
總之你分配的LruCache大小既不能太大,又不能太小,具體到應(yīng)用中還要你綜合考慮。
下面的代碼是使用LruCache的例子:
private LruCachemMemoryCache;//聲明緩存空間
final int maxMemory = (int)(Runtime.getRuntime().maxMemory() / 1024);//獲取應(yīng)用在系統(tǒng)中的最大內(nèi)存分配
//分配1/8的應(yīng)用內(nèi)存作為緩存空間
final int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
//重寫(xiě)sizeOf方法,返回圖片的占用字節(jié)數(shù)而不是圖片的個(gè)數(shù),
//每次添加圖片是會(huì)被調(diào)用
return bitmap.getByteCount() / 1024;
}
};
注意:有同學(xué)可能會(huì)問(wèn)下面的代碼:
int cacheSize=4*1024*1024;// 4MiB
LruCache bitmapCache=new LruCache(cacheSize){
protected int sizeOf(Stringkey,Bitmapvalue){
return value.getByteCount();
}
}
這兩個(gè)sizeOf的計(jì)算是不一樣的,這里說(shuō)明一下,這個(gè)方法重寫(xiě)的目的是返回圖片占用的緩存空間而不是圖片的數(shù)目,并且這個(gè)數(shù)值的單位要和cacheSize一樣。
總結(jié):
綜合上面的講解,在使用內(nèi)存緩存LruCache時(shí)你需要知道如下知識(shí):
LruCache封裝了LinkedHashMap,提供了LRU(Least Recently Used 最近最少使用算法)緩存的功能;
LruCache通過(guò)trimToSize方法自動(dòng)刪除最近最少訪問(wèn)的鍵值對(duì);
LruCache不允許空鍵值,LinkedHashMap允許;
LruCache線程安全,LinkedHashMap線程不安全;
繼承LruCache時(shí),必須要復(fù)寫(xiě)sizeOf方法,用于計(jì)算每個(gè)條目的大小。在put和get的時(shí)候會(huì)調(diào)用safeSizeOf(Kkey, V value),safeSizeOf(K key, V value)會(huì)調(diào)用 sizeOf (K key, V value),這個(gè)方法默認(rèn)返回1。
本文由磨礪營(yíng)IT教育整理,向跟著威哥學(xué)習(xí)Android或java的朋友關(guān)注微信公眾號(hào)mjw-java或訪問(wèn)www.moliying.com/?jianshu