1系吩、什么是緩存笑诅?
緩存技術(shù)原理就是把用戶訪問的所有對(duì)象看作一個(gè)全集吐辙,經(jīng)過算法標(biāo)記哪些是用戶經(jīng)常訪問的對(duì)象宣决,把這些對(duì)象放到一個(gè)集合里,這個(gè)集合是全集一個(gè)子集昏苏,下一次用戶再訪問的時(shí)候會(huì)先從這個(gè)子集集合中查找用戶要訪問的對(duì)象如果找到就直接返回這個(gè)對(duì)象尊沸,如果沒有找到則再去全集中查找。當(dāng)然了我這里說的只是原理性的東西贤惯,緩存是有很多算法的洼专,并且有的不止一級(jí)緩存,這里就不過多講了孵构。
2屁商、為什么要用到緩存?
有緩存的話可以不必每次從源地址讀取文件颈墅,既節(jié)省了時(shí)間也節(jié)省了流量棒假。尤其是手機(jī)設(shè)備,頻繁的訪問網(wǎng)絡(luò)資源會(huì)消耗很多用戶的流量和電量精盅,這是用戶不能忍受的,所以無論從哪個(gè)方面考慮應(yīng)用程序都必須加上緩存谜酒。
3叹俏、Android中的圖片緩存有哪些?各有什么特點(diǎn)僻族?
Android設(shè)備的圖片緩存分兩種粘驰,一種是內(nèi)存緩存屡谐,圖片緩存在設(shè)備的內(nèi)存中,一種是外部緩存蝌数,圖片緩存在磁盤上愕掏,磁盤可以是內(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)給出意見作為參考:
分配LruCache大小的時(shí)候考慮你的應(yīng)用剩余內(nèi)存有多大;
一次屏幕顯示多少?gòu)垐D片丐箩,有多少?gòu)垐D片是緩存起來準(zhǔn)備顯示的摇邦;
考慮你的手機(jī)分辨率和尺寸, 緩存相同的圖片個(gè)數(shù)屎勘,dpi越大的手機(jī)需要的內(nèi)存就會(huì)越大施籍;
圖片分辨率和像素質(zhì)量也決定了占用內(nèi)存的大小概漱;
圖片訪問的頻繁程度是多少丑慎,是不是有一些圖片是經(jīng)常訪問的?如果存在你可以考慮用多個(gè)·LruCache來做緩存,按照訪問的頻率度分配到不同的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) {
//重寫sizeOf方法影斑,返回圖片的占用字節(jié)數(shù)而不是圖片的個(gè)數(shù),
//每次添加圖片是會(huì)被調(diào)用
return bitmap.getByteCount() / 1024;
}
};
注意:有同學(xué)可能會(huì)問下面的代碼:
int cacheSize=4*1024*1024;// 4MiB
LruCache bitmapCache=new LruCache(cacheSize){
protected int sizeOf(Stringkey,Bitmapvalue){
return value.getByteCount();
}
}
這兩個(gè)sizeOf的計(jì)算是不一樣的这嚣,這里說明一下鸥昏,這個(gè)方法重寫的目的是返回圖片占用的緩存空間而不是圖片的數(shù)目,并且這個(gè)數(shù)值的單位要和cacheSize一樣姐帚。
總結(jié):
綜合上面的講解吏垮,在使用內(nèi)存緩存LruCache時(shí)你需要知道如下知識(shí):
LruCache封裝了LinkedHashMap,提供了LRU(Least Recently Used 最近最少使用算法)緩存的功能罐旗;
LruCache通過trimToSize方法自動(dòng)刪除最近最少訪問的鍵值對(duì)膳汪;
LruCache不允許空鍵值,LinkedHashMap允許九秀;
LruCache線程安全遗嗽,LinkedHashMap線程不安全;
繼承LruCache時(shí)鼓蜒,必須要復(fù)寫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或訪問www.moliying.com/?jianshu