日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

三分钟学会缓存工具DiskLruCache

發(fā)布時(shí)間:2023/12/9 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 三分钟学会缓存工具DiskLruCache 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

DiskLruCache是一個(gè)十分好用的android緩存工具,我們可以從GitHub上下載其源碼:https://github.com/JakeWharton/DiskLruCache

DiskLruCache所有的數(shù)據(jù)都存儲(chǔ)在/storage/emulated/0/Android/data/應(yīng)用包名/cache/XXX文件夾中(你也可以修改,但不建議這樣做,原因請(qǐng)繼續(xù)往下看),這個(gè)是android系統(tǒng)默認(rèn)的應(yīng)用緩存位置,如果應(yīng)用被刪除,這個(gè)文件也會(huì)一起被刪除,避免應(yīng)用刪除后有殘留數(shù)據(jù)的問(wèn)題。同時(shí),由于數(shù)據(jù)沒(méi)有存儲(chǔ)在硬盤里,所以不會(huì)影響系統(tǒng)性能,在sd卡里,你可以存儲(chǔ)任意多數(shù)據(jù)。
由于DiskLruCache是被final修飾的,因此不可以直接通過(guò)new獲得它的實(shí)例,我們使用它的open方法獲得它的一個(gè)實(shí)例:
public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
open方法需要四個(gè)參數(shù),第一個(gè)是緩存文件文件的位置,通過(guò)下面的方法可得到:

private File getDiskCacheDir(Context context, String uniqueName) {String cachePath;//如果sd卡存在并且沒(méi)有被移除if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())|| !Environment.isExternalStorageRemovable()) {cachePath = context.getExternalCacheDir().getPath();} else {cachePath = context.getCacheDir().getPath();}return new File(cachePath + File.separator + uniqueName);}

第二個(gè)參數(shù)是應(yīng)用程序的版本號(hào),要傳入版本號(hào)是因?yàn)槿绻麘?yīng)用升級(jí)緩存會(huì)被清除掉。通過(guò)下面的方法可以獲得程序的版本號(hào):

private int getAppVersion(Context context) {try {PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);return info.versionCode;} catch (NameNotFoundException e) {e.printStackTrace();}return 1;}

第三個(gè)參數(shù)表示同一個(gè)key可以對(duì)應(yīng)多少個(gè)緩存文件,一般情況下我們都是傳1,這樣key和緩存文件一一對(duì)應(yīng),查找和移除都會(huì)比較方便。
第四個(gè)參數(shù)表示最大可以緩存多少字節(jié)的數(shù)據(jù)。
打開(kāi)了DiskLruCache之后,我們可以看看怎么向DiskLruCache中緩存數(shù)據(jù):
先來(lái)看看從網(wǎng)上down一張圖片:

private boolean downloadImg(final String urlStr,final OutputStream outputStream) {HttpURLConnection conn = null;BufferedOutputStream out = null;BufferedInputStream in = null;try {URL url = new URL(urlStr);conn = (HttpURLConnection) url.openConnection();in = new BufferedInputStream(conn.getInputStream(), 8 * 1024);out = new BufferedOutputStream(outputStream, 8 * 1024);int len = 0;while ((len = in.read()) != -1) {out.write(len);}return true;} catch (IOException e) {e.printStackTrace();} finally {if (conn != null)conn.disconnect();try {if (out != null)out.close();} catch (IOException e) {e.printStackTrace();}try {if (in != null)in.close();} catch (IOException e) {e.printStackTrace();}}return false;}

這是一個(gè)簡(jiǎn)單的聯(lián)網(wǎng)down圖片代碼,拿到圖片后就可以緩存到本地了,但是對(duì)于每一個(gè)存儲(chǔ)資源都需要有一個(gè)key,這個(gè)key要是唯一的,而且這個(gè)key最長(zhǎng)120個(gè)字符,且只能包括a-z,0-9,下劃線以及減號(hào),一次我們可以采用Java中的UUID來(lái)得到key,也可以使用MD5加密網(wǎng)址得到一個(gè)key,我這里采用md5,方法如下:

public class MD5Util {public final static String md5(String pwd) {//用于加密的字符char md5String[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9','A', 'B', 'C', 'D', 'E', 'F' };try {//使用平臺(tái)的默認(rèn)字符集將此 String 編碼為 byte序列,并將結(jié)果存儲(chǔ)到一個(gè)新的 byte數(shù)組中byte[] btInput = pwd.getBytes();// 獲得指定摘要算法的 MessageDigest對(duì)象,此處為MD5//MessageDigest類為應(yīng)用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法。//信息摘要是安全的單向哈希函數(shù),它接收任意大小的數(shù)據(jù),并輸出固定長(zhǎng)度的哈希值。 MessageDigest mdInst = MessageDigest.getInstance("MD5");//System.out.println(mdInst); //MD5 Message Digest from SUN, <initialized>//MessageDigest對(duì)象通過(guò)使用 update方法處理數(shù)據(jù), 使用指定的byte數(shù)組更新摘要mdInst.update(btInput);//System.out.println(mdInst); //MD5 Message Digest from SUN, <in progress>// 摘要更新之后,通過(guò)調(diào)用digest()執(zhí)行哈希計(jì)算,獲得密文byte[] md = mdInst.digest();//System.out.println(md);// 把密文轉(zhuǎn)換成十六進(jìn)制的字符串形式int j = md.length;//System.out.println(j);char str[] = new char[j * 2];int k = 0;for (int i = 0; i < j; i++) { // i = 0byte byte0 = md[i]; //95str[k++] = md5String[byte0 >>> 4 & 0xf]; // 5 str[k++] = md5String[byte0 & 0xf]; // F}//返回經(jīng)過(guò)加密后的字符串return new String(str);} catch (Exception e) {e.printStackTrace();return null;}} }

各位看官在使用的時(shí)候記得把md5String[]中大寫的字母改為小寫,因?yàn)閗ey中如果有大寫字母驗(yàn)證會(huì)不通過(guò)。當(dāng)然,你也可以修改DiskLruCache的源碼從而讓它支持大寫字母,修改的地方:

現(xiàn)在萬(wàn)事俱備,我們來(lái)把圖片緩存起來(lái),由于聯(lián)網(wǎng)是好事操作,所以要在新線程中完成,完整的方法如下:

private void cacheImg() {new Thread(new Runnable() {@Overridepublic void run() {String key = MD5Util.md5(IMGIP);try {DiskLruCache.Editor editor = mDiskLruCache.edit(key);if (editor != null) {OutputStream out = editor.newOutputStream(0);if (downloadImg(IMGIP, out)) {//提交editor.commit();} else {//撤銷操作editor.abort();}}/*** 這個(gè)方法用于將內(nèi)存中的操作記錄同步到日志文件(也就是journal文件)當(dāng)中。* 這個(gè)方法非常重要,因?yàn)镈iskLruCache能夠正常工作的前提就是要依賴于journal文件中的內(nèi)容。* 并不是每次寫入緩存都要調(diào)用一次flush()方法的,頻繁地調(diào)用并不會(huì)帶來(lái)任何好處,* 只會(huì)額外增加同步j(luò)ournal文件的時(shí)間。* 比較標(biāo)準(zhǔn)的做法就是在Activity的onPause()方法中去調(diào)用一次flush()方法就可以了*/mDiskLruCache.flush();} catch (IOException e) {e.printStackTrace();}}}).start();}

editor.newOutputStream(0);方法有一個(gè)參數(shù),查看源碼我們知道這個(gè)參數(shù)必須大于0并且小于valueCount,前文中valueCount我們已經(jīng)設(shè)置為1了,所以這里只能取值0。這個(gè)時(shí)候打開(kāi)你的緩存文件夾,/storage/emulated/0/Android/data/應(yīng)用包名/cache/XXX,里邊已經(jīng)有了我們緩存的數(shù)據(jù)了:

好了,數(shù)據(jù)存下來(lái)了,接下來(lái)就是讀取,每一個(gè)緩存文件都對(duì)應(yīng)一個(gè)key,讀取就是根據(jù)這個(gè)key來(lái)讀取:

private void showImg() {String key = MD5Util.md5(IMGIP); try {DiskLruCache.Snapshot snapShot = mDiskLruCache.get(key);if(snapShot!=null){InputStream is = snapShot.getInputStream(0);Bitmap bitmap = BitmapFactory.decodeStream(is);im.setImageBitmap(bitmap);}} catch (IOException e) {e.printStackTrace();} }

讀取的時(shí)候我們最先拿到的是一個(gè)Snapshot 對(duì)象,再根據(jù)我們之前傳入的參數(shù)0拿到緩存文件的流,最后把流轉(zhuǎn)換為圖片。

到這里大家可能就明白了,之前的editor.newOutputStream(0);方法為什么會(huì)有一個(gè)0的參數(shù)了,相當(dāng)于一個(gè)標(biāo)識(shí),讀取時(shí)也傳入?yún)?shù)0才能讀到我們想要的數(shù)據(jù)。(加入我們的key與緩存文件不是一一對(duì)應(yīng),也就是我們一開(kāi)始的open方法中傳入的不是valueCount的值不是1,那么一個(gè)key對(duì)應(yīng)多個(gè)緩存文件我們要怎么區(qū)分?就是通過(guò)這種方式,有興趣的同學(xué)查看源碼就一目了然了)。

下來(lái)就是清除緩存了,看方法:

private void clearCache() {String key = MD5Util.md5(IMGIP);try {mDiskLruCache.remove(key);} catch (IOException e) {e.printStackTrace();} }

根據(jù)緩存文件的key,調(diào)用remove方法,將該緩存文件移除。

下來(lái)是查看緩存大小:

像鳳凰新聞客戶端中顯示緩存大小,這個(gè)數(shù)值我們可以通過(guò)size()方法直接拿到:

private void getCacheSize() {tv.setText(mDiskLruCache.size()+"");}

大家應(yīng)該看到了鳳凰新聞還有一個(gè)功能就是清除緩存,這個(gè)功能直接調(diào)用delete方法就能實(shí)現(xiàn):

private void deleteAll() {/*** 這個(gè)方法用于將所有的緩存數(shù)據(jù)全部刪除* 其實(shí)只需要調(diào)用一下DiskLruCache的delete()方法就可以實(shí)現(xiàn)了。* 會(huì)刪除包括日志文件在內(nèi)的所有文件*/try {mDiskLruCache.delete();} catch (IOException e) {e.printStackTrace();}}

所有功能都完成之后,我們要記得在onDestory方法中關(guān)閉DiskLruCache。

@Overrideprotected void onDestroy() {super.onDestroy();/*** 這個(gè)方法用于將DiskLruCache關(guān)閉掉,是和open()方法對(duì)應(yīng)的一個(gè)方法。* 關(guān)閉掉了之后就不能再調(diào)用DiskLruCache中任何操作緩存數(shù)據(jù)的方法,* 通常只應(yīng)該在Activity的onDestroy()方法中去調(diào)用close()方法。*/try {mDiskLruCache.close();} catch (IOException e) {e.printStackTrace();}}

到此,我想大家已經(jīng)基本會(huì)用這個(gè)東東了吧。

最后奉上本文源碼下載地址http://pan.baidu.com/s/1kTzSHtd

版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。若有錯(cuò)誤地方,還望批評(píng)指正,不勝感激。

轉(zhuǎn)載于:https://www.cnblogs.com/lenve/p/4770527.html

總結(jié)

以上是生活随笔為你收集整理的三分钟学会缓存工具DiskLruCache的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。