Android圖片緩存之Lru算法

Lru:

LRU是Least Recently Used 的縮寫,翻譯過來就是“最近最少使用”,LRU緩存就是使用這種原理實(shí)現(xiàn),簡單的說就是緩存一定量的數(shù)據(jù),當(dāng)超過設(shè)定的閾值時(shí)就把一些過期的數(shù)據(jù)刪除掉,比如我們緩存10000條數(shù)據(jù),當(dāng)數(shù)據(jù)小于10000時(shí)可以隨意添加,當(dāng)超過10000時(shí)就需要把新的數(shù)據(jù)添加進(jìn)來,同時(shí)要把過期數(shù)據(jù)刪除,以確保我們最大緩存10000條,那怎么確定刪除哪條過期數(shù)據(jù)呢,采用LRU算法實(shí)現(xiàn)的話就是將最老的數(shù)據(jù)刪掉。

基于LruCache實(shí)現(xiàn)內(nèi)存緩存:

1.)初始化MemoryCache

這里內(nèi)存緩存的是Drawable 而不是Bitmap 理由是Drawable相對Bitmap來說有很大的內(nèi)存優(yōu)勢

intmaxMemory = (int) Runtime.getRuntime().maxMemory();//獲取系統(tǒng)分配給應(yīng)用的總內(nèi)存大小intmCacheSize = maxMemory / 8;//設(shè)置圖片內(nèi)存緩存占用八分之一mMemoryCache =newLruCache(mCacheSize) {//必須重寫此方法,來測量Bitmap的大小@OverrideprotectedintsizeOf(String key, Drawable value) {if(valueinstanceofBitmapDrawable) {

Bitmap bitmap=((BitmapDrawable) value).getBitmap();returnbitmap ==null? 0: bitmap.getByteCount();

}returnsuper.sizeOf(key, value);

}

};

2.)添加一個(gè)Drawable到內(nèi)存緩存

/*** 添加Drawable到內(nèi)存緩存

*

*@paramkey

*@paramdrawable*/privatevoidaddDrawableToMemoryCache(String key, Drawable drawable) {if(getDrawableFromMemCache(key) ==null&& drawable !=null) {

mMemoryCache.put(key, drawable);

}

}

3.)從內(nèi)存緩存中獲取一個(gè)Drawable

/*** 從內(nèi)存緩存中獲取一個(gè)Drawable

*

*@paramkey

*@return*/publicDrawable getDrawableFromMemCache(String key) {returnmMemoryCache.get(key);

}

4.)從內(nèi)存緩存中移除一個(gè)Drawable

/*** 從內(nèi)存緩存中移除

*

*@paramkey*/publicvoidremoveCacheFromMemory(String key) {

mMemoryCache.remove(key);

}

5.)清空內(nèi)存緩存

/*** 清理內(nèi)存緩存*/publicvoidcleanMemoryCCache() {

mMemoryCache.evictAll();

}

其實(shí)Lru緩存機(jī)制本質(zhì)上就是存儲(chǔ)在一個(gè)LinkedHashMap存儲(chǔ),為了保障插入的數(shù)據(jù)順序,方便清理。

基于DiskLruCache實(shí)現(xiàn)磁盤緩存:

DiskLruCache類并不是谷歌官方實(shí)現(xiàn),需要自行下載,下載地址:https://github.com/JakeWharton/DiskLruCache

1.)初始化DiskLruCache

File cacheDir = context.getCacheDir();//指定的是數(shù)據(jù)的緩存地址longdiskCacheSize = 1024 * 1024 * 30;//最多可以緩存多少字節(jié)的數(shù)據(jù)intappVersion = DiskLruUtils.getAppVersion(context);//指定當(dāng)前應(yīng)用程序的版本號intvalueCount = 1;//指定同一個(gè)key可以對應(yīng)多少個(gè)緩存文件try{

mDiskCache=DiskLruCache.open(cacheDir, appVersion, valueCount, diskCacheSize);

}catch(Exception ex) {

}

2.)寫入一個(gè)文件到磁盤緩存

/*** 添加Bitmap到磁盤緩存

*

*@paramkey

*@paramvalue*/privatevoidaddBitmapToDiskCache(String key,byte[] value) {

OutputStream out=null;try{

DiskLruCache.Editor editor=mDiskCache.edit(key);if(editor !=null) {

out= editor.newOutputStream(0);if(value !=null&& value.length > 0) {

out.write(value);

out.flush();

editor.commit();

}else{

editor.abort();

}

}

mDiskCache.flush();

}catch(IOException e) {

e.printStackTrace();

}finally{

DiskLruUtils.closeQuietly(out);

}

}

3.)從磁盤緩存中讀取Drawable

/*** 從磁盤緩存中獲取一個(gè)Drawable

*

*@paramkey

*@return*/publicDrawable getDrawableFromDiskCache(String key) {try{

DiskLruCache.Snapshot snapShot=mDiskCache.get(key);if(snapShot !=null) {

InputStream is= snapShot.getInputStream(0);

Bitmap bitmap=BitmapFactory.decodeStream(is);

Drawable drawable=DiskLruUtils.bitmap2Drawable(bitmap);//從磁盤中讀取到之后 加入內(nèi)存緩存addDrawableToMemoryCache(key, drawable);returndrawable;

}

}catch(IOException e) {

e.printStackTrace();

}returnnull;

}

4.)從磁盤緩存中移除

/*** 從磁盤緩存中移除

*

*@paramkey*/publicvoidremoveCacheFromDisk(String key) {try{

mDiskCache.remove(key);

}catch(Exception e) {

}

}

5.)清空磁盤緩存

/*** 清理磁盤緩存*/publicvoidcleanDiskCache() {try{

mDiskCache.delete();

}catch(Exception e) {

}

}

圖片下載過程:

接下來實(shí)例中用到了一點(diǎn)RxJava的知識有不了解RxJava的請自行了解一下。

1.)采用異步方式操作磁盤緩存和網(wǎng)絡(luò)下載, 內(nèi)存緩存可以在主線程中操作

publicvoiddisPlay(finalImageView imageView, String imageUrl) {//生成唯一keyfinalString key =DiskLruUtils.hashKeyForDisk(imageUrl);//先從內(nèi)存中讀取Drawable drawableFromMemCache =getDrawableFromMemCache(key);if(drawableFromMemCache !=null) {

imageView.setImageDrawable(drawableFromMemCache);return;

}

Observable.just(imageUrl)

.map(newFunc1() {

@OverridepublicDrawable call(String imageUrl) {//參數(shù)類型 String//從磁盤中讀取Drawable drawableFromDiskCache =getDrawableFromDiskCache(key);if(drawableFromDiskCache !=null) {returndrawableFromDiskCache;

}//網(wǎng)絡(luò)下載returndownload(imageUrl);//返回類型 Drawable}

})

.subscribeOn(Schedulers.io())//指定 subscribe() 發(fā)生在 IO 線程.observeOn(AndroidSchedulers.mainThread())//指定 Subscriber 的回調(diào)發(fā)生在主線程.subscribe(newAction1() {

@Overridepublicvoidcall(Drawable drawable) {//參數(shù)類型 DrawableimageView.setImageDrawable(drawable);

}

});

}

2.)下載圖片過程以及處理

privateDrawable download(String imageUrl) {

HttpURLConnection urlConnection=null;

ByteArrayOutputStream bos=null;

InputStream ins=null;try{finalURL url =newURL(imageUrl);

urlConnection=(HttpURLConnection) url.openConnection();

ins=urlConnection.getInputStream();

bos=newByteArrayOutputStream();intb;while((b = ins.read()) != -1) {

bos.write(b);

}

bos.flush();byte[] bytes =bos.toByteArray();

Bitmap bitmap=DiskLruUtils.bytes2Bitmap(bytes);

String key=DiskLruUtils.hashKeyForDisk(imageUrl);

Drawable drawable=DiskLruUtils.bitmap2Drawable(bitmap);//加入內(nèi)存緩存addDrawableToMemoryCache(key, drawable);//加入磁盤緩存addBitmapToDiskCache(key, bytes);returndrawable;

}catch(IOException e) {

e.printStackTrace();

}finally{if(urlConnection !=null) {

urlConnection.disconnect();

}

DiskLruUtils.closeQuietly(bos);

DiskLruUtils.closeQuietly(ins);

}returnnull;

}

附上最終圖片緩存單例簡單實(shí)現(xiàn)全部代碼以及DiskLruUtils工具類代碼

ImageLoadManager.java

ImageLoadManager.java

DiskLruUtils.java

DiskLruUtils.java

總結(jié):

以上就是基于Lru圖片緩存簡單實(shí)現(xiàn)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容