www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 芯聞號(hào) > 充電吧
[導(dǎo)讀]下載好了,對(duì)DiskLruCache有了最初的認(rèn)識(shí)之后,下面我們來(lái)學(xué)習(xí)一下DiskLruCache的用法吧。由于DiskLruCache并不是由Google官方編寫的,所以這個(gè)類并沒(méi)有被包含在Andr

下載

好了,對(duì)DiskLruCache有了最初的認(rèn)識(shí)之后,下面我們來(lái)學(xué)習(xí)一下DiskLruCache的用法吧。由于DiskLruCache并不是由Google官方編寫的,所以這個(gè)類并沒(méi)有被包含在Android?API當(dāng)中,我們需要將這個(gè)類從網(wǎng)上下載下來(lái),然后手動(dòng)添加到項(xiàng)目當(dāng)中。DiskLruCache的源碼在Google?Source上,地址在文章底部,下載好了源碼之后,只需要在項(xiàng)目中新建一個(gè)libcore.io包,然后將DiskLruCache.java文件復(fù)制到這個(gè)包中即可。

打開(kāi)緩存

這樣的話我們就把準(zhǔn)備工作做好了,下面看一下DiskLruCache到底該如何使用。首先你要知道,DiskLruCache是不能new出實(shí)例的,如果我們要?jiǎng)?chuàng)建一個(gè)DiskLruCache的實(shí)例,則需要調(diào)用它的open()方法,接口如下所示:

1

public?static?DiskLruCache?open(File?directory,?int?appVersion,?int?valueCount,?long?maxSize)

open()方法接收四個(gè)參數(shù),第一個(gè)參數(shù)指定的是數(shù)據(jù)的緩存地址,第二個(gè)參數(shù)指定當(dāng)前應(yīng)用程序的版本號(hào),第三個(gè)參數(shù)指定同一個(gè)key可以對(duì)應(yīng)多少個(gè)緩存文件,基本都是傳1,第四個(gè)參數(shù)指定最多可以緩存多少字節(jié)的數(shù)據(jù)。

其中緩存地址前面已經(jīng)說(shuō)過(guò)了,通常都會(huì)存放在?/sdcard/Android/data/

1

2

3

4

5

6

7

8

9

10

public?File?getDiskCacheDir(Context?context,?String?uniqueName)?{??

????String?cachePath;??

????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);??

}

可以看到,當(dāng)SD卡存在或者SD卡不可被移除的時(shí)候,就調(diào)用getExternalCacheDir()方法來(lái)獲取緩存路徑,否則就調(diào)用getCacheDir()方法來(lái)獲取緩存路徑。前者獲取到的就是?/sdcard/Android/data/

接著又將獲取到的路徑和一個(gè)uniqueName進(jìn)行拼接,作為最終的緩存路徑返回。那么這個(gè)uniqueName又是什么呢?其實(shí)這就是為了對(duì)不同類型的數(shù)據(jù)進(jìn)行區(qū)分而設(shè)定的一個(gè)唯一值,比如說(shuō)在網(wǎng)易新聞緩存路徑下看到的bitmap、object等文件夾。

接著是應(yīng)用程序版本號(hào),我們可以使用如下代碼簡(jiǎn)單地獲取到當(dāng)前應(yīng)用程序的版本號(hào):

1

2

3

4

5

6

7

8

9

public?int?getAppVersion(Context?context)?{??

????try?{??

????????PackageInfo?info?=?context.getPackageManager().getPackageInfo(context.getPackageName(),?0);??

????????return?info.versionCode;??

????}?catch?(NameNotFoundException?e)?{??

????????e.printStackTrace();??

????}??

????return?1;??

}

需要注意的是,每當(dāng)版本號(hào)改變,緩存路徑下存儲(chǔ)的所有數(shù)據(jù)都會(huì)被清除掉,因?yàn)镈iskLruCache認(rèn)為當(dāng)應(yīng)用程序有版本更新的時(shí)候,所有的數(shù)據(jù)都應(yīng)該從網(wǎng)上重新獲取。

后面兩個(gè)參數(shù)就沒(méi)什么需要解釋的了,第三個(gè)參數(shù)傳1,第四個(gè)參數(shù)通常傳入10M的大小就夠了,這個(gè)可以根據(jù)自身的情況進(jìn)行調(diào)節(jié)。

因此,一個(gè)非常標(biāo)準(zhǔn)的open()方法就可以這樣寫:


1

2

3

4

5

6

7

8

9

10

DiskLruCache?mDiskLruCache?=?null;??

try?{??

????File?cacheDir?=?getDiskCacheDir(context,?"bitmap");??

????if?(!cacheDir.exists())?{??

????????cacheDir.mkdirs();??

????}??

????mDiskLruCache?=?DiskLruCache.open(cacheDir,?getAppVersion(context),?1,?10?*?1024?*?1024);??

}?catch?(IOException?e)?{??

????e.printStackTrace();??

}

首先調(diào)用getDiskCacheDir()方法獲取到緩存地址的路徑,然后判斷一下該路徑是否存在,如果不存在就創(chuàng)建一下。接著調(diào)用DiskLruCache的open()方法來(lái)創(chuàng)建實(shí)例,并把四個(gè)參數(shù)傳入即可。

有了DiskLruCache的實(shí)例之后,我們就可以對(duì)緩存的數(shù)據(jù)進(jìn)行操作了,操作類型主要包括寫入、訪問(wèn)、移除等,我們一個(gè)個(gè)進(jìn)行學(xué)習(xí)。

寫入緩存

先來(lái)看寫入,比如說(shuō)現(xiàn)在有一張圖片,地址是http://img.my.csdn.net/uploads/201309/01/1378037235_7476.jpg,那么為了將這張圖片下載下來(lái),就可以這樣寫:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

private?boolean?downloadUrlToStream(String?urlString,?OutputStream?outputStream)?{??

????HttpURLConnection?urlConnection?=?null;??

????BufferedOutputStream?out?=?null;??

????BufferedInputStream?in?=?null;??

????try?{??

????????final?URL?url?=?new?URL(urlString);??

????????urlConnection?=?(HttpURLConnection)?url.openConnection();??

????????in?=?new?BufferedInputStream(urlConnection.getInputStream(),?8?*?1024);??

????????out?=?new?BufferedOutputStream(outputStream,?8?*?1024);??

????????int?b;??

????????while?((b?=?in.read())?!=?-1)?{??

????????????out.write(b);??

????????}??

????????return?true;??

????}?catch?(final?IOException?e)?{??

????????e.printStackTrace();??

????}?finally?{??

????????if?(urlConnection?!=?null)?{??

????????????urlConnection.disconnect();??

????????}??

????????try?{??

????????????if?(out?!=?null)?{??

????????????????out.close();??

????????????}??

????????????if?(in?!=?null)?{??

????????????????in.close();??

????????????}??

????????}?catch?(final?IOException?e)?{??

????????????e.printStackTrace();??

????????}??

????}??

????return?false;??

}

這段代碼相當(dāng)基礎(chǔ),相信大家都看得懂,就是訪問(wèn)urlString中傳入的網(wǎng)址,并通過(guò)outputStream寫入到本地。有了這個(gè)方法之后,下面我們就可以使用DiskLruCache來(lái)進(jìn)行寫入了,寫入的操作是借助DiskLruCache.Editor這個(gè)類完成的。類似地,這個(gè)類也是不能new的,需要調(diào)用DiskLruCache的edit()方法來(lái)獲取實(shí)例,接口如下所示:

雙擊代碼復(fù)制

1

public?Editor?edit(String?key)?throws?IOException

可以看到,edit()方法接收一個(gè)參數(shù)key,這個(gè)key將會(huì)成為緩存文件的文件名,并且必須要和圖片的URL是一一對(duì)應(yīng)的。那么怎樣才能讓key和圖片的URL能夠一一對(duì)應(yīng)呢?直接使用URL來(lái)作為key?不太合適,因?yàn)閳D片URL中可能包含一些特殊字符,這些字符有可能在命名文件時(shí)是不合法的。其實(shí)最簡(jiǎn)單的做法就是將圖片的URL進(jìn)行MD5編碼,編碼后的字符串肯定是唯一的,并且只會(huì)包含0-F這樣的字符,完全符合文件的命名規(guī)則。

那么我們就寫一個(gè)方法用來(lái)將字符串進(jìn)行MD5編碼,代碼如下所示:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

public?String?hashKeyForDisk(String?key)?{??

????String?cacheKey;??

????try?{??

????????final?MessageDigest?mDigest?=?MessageDigest.getInstance("MD5");??

????????mDigest.update(key.getBytes());??

????????cacheKey?=?bytesToHexString(mDigest.digest());??

????}?catch?(NoSuchAlgorithmException?e)?{??

????????cacheKey?=?String.valueOf(key.hashCode());??

????}??

????return?cacheKey;??

}??

???

private?String?bytesToHexString(byte[]?bytes)?{??

????StringBuilder?sb?=?new?StringBuilder();??

????for?(int?i?=?0;?i?<?bytes.length;?i++)?{??

????????String?hex?=?Integer.toHexString(0xFF?&?bytes[i]);??

????????if?(hex.length()?==?1)?{??

????????????sb.append('0');??

????????}??

????????sb.append(hex);??

????}??

????return?sb.toString();??

}

代碼很簡(jiǎn)單,現(xiàn)在我們只需要調(diào)用一下hashKeyForDisk()方法,并把圖片的URL傳入到這個(gè)方法中,就可以得到對(duì)應(yīng)的key了。

因此,現(xiàn)在就可以這樣寫來(lái)得到一個(gè)DiskLruCache.Editor的實(shí)例:

1

2

3

String?imageUrl?=?"http://img.21ic.com/21ic_pic/CSDN/=utf-8' '1378037235_7476.jpg";??

String?key?=?hashKeyForDisk(imageUrl);??

DiskLruCache.Editor?editor?=?mDiskLruCache.edit(key);

有了DiskLruCache.Editor的實(shí)例之后,我們可以調(diào)用它的newOutputStream()方法來(lái)創(chuàng)建一個(gè)輸出流,然后把它傳入到downloadUrlToStream()中就能實(shí)現(xiàn)下載并寫入緩存的功能了。注意newOutputStream()方法接收一個(gè)index參數(shù),由于前面在設(shè)置valueCount的時(shí)候指定的是1,所以這里index傳0就可以了。在寫入操作執(zhí)行完之后,我們還需要調(diào)用一下commit()方法進(jìn)行提交才能使寫入生效,調(diào)用abort()方法的話則表示放棄此次寫入。

因此,一次完整寫入操作的代碼如下所示:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

new?Thread(new?Runnable()?{??

????@Override?

????public?void?run()?{??

????????try?{??

????????????String?imageUrl?=?"http://img.21ic.com/21ic_pic/CSDN/=utf-8' '1378037235_7476.jpg";??

????????????String?key?=?hashKeyForDisk(imageUrl);??

????????????DiskLruCache.Editor?editor?=?mDiskLruCache.edit(key);??

????????????if?(editor?!=?null)?{??

????????????????OutputStream?outputStream?=?editor.newOutputStream(0);??

????????????????if?(downloadUrlToStream(imageUrl,?outputStream))?{??

????????????????????editor.commit();??

????????????????}?else?{??

????????????????????editor.abort();??

????????????????}??

????????????}??

????????????mDiskLruCache.flush();??

????????}?catch?(IOException?e)?{??

????????????e.printStackTrace();??

????????}??

????}??

}).start();

由于這里調(diào)用了downloadUrlToStream()方法來(lái)從網(wǎng)絡(luò)上下載圖片,所以一定要確保這段代碼是在子線程當(dāng)中執(zhí)行的。注意在代碼的最后我還調(diào)用了一下flush()方法,這個(gè)方法并不是每次寫入都必須要調(diào)用的,但在這里卻不可缺少,我會(huì)在后面說(shuō)明它的作用。

現(xiàn)在的話緩存應(yīng)該是已經(jīng)成功寫入了,我們進(jìn)入到SD卡上的緩存目錄里看一下,如下圖所示:

可以看到,這里有一個(gè)文件名很長(zhǎng)的文件,和一個(gè)journal文件,那個(gè)文件名很長(zhǎng)的文件自然就是緩存的圖片了,因?yàn)槭鞘褂昧薓D5編碼來(lái)進(jìn)行命名的。

讀取緩存

緩存已經(jīng)寫入成功之后,接下來(lái)我們就該學(xué)習(xí)一下如何讀取了。讀取的方法要比寫入簡(jiǎn)單一些,主要是借助DiskLruCache的get()方法實(shí)現(xiàn)的,接口如下所示:

1

public?synchronized?Snapshot?get(String?key)?throws?IOException

很明顯,get()方法要求傳入一個(gè)key來(lái)獲取到相應(yīng)的緩存數(shù)據(jù),而這個(gè)key毫無(wú)疑問(wèn)就是將圖片URL進(jìn)行MD5編碼后的值了,因此讀取緩存數(shù)據(jù)的代碼就可以這樣寫:

1

2

3

String?imageUrl?=?"http://img.21ic.com/21ic_pic/CSDN/=utf-8' '1378037235_7476.jpg";??

String?key?=?hashKeyForDisk(imageUrl);??

DiskLruCache.Snapshot?snapShot?=?mDiskLruCache.get(key);

很奇怪的是,這里獲取到的是一個(gè)DiskLruCache.Snapshot對(duì)象,這個(gè)對(duì)象我們?cè)撛趺蠢媚??很?jiǎn)單,只需要調(diào)用它的getInputStream()方法就可以得到緩存文件的輸入流了。同樣地,getInputStream()方法也需要傳一個(gè)index參數(shù),這里傳入0就好。有了文件的輸入流之后,想要把緩存圖片顯示到界面上就輕而易舉了。所以,一段完整的讀取緩存,并將圖片加載到界面上的代碼如下所示:

1

2

3

4

5

6

7

8

9

10

11

12

try?{??

????String?imageUrl?=?"http://img.21ic.com/21ic_pic/CSDN/=utf-8' '1378037235_7476.jpg";??

????String?key?=?hashKeyForDisk(imageUrl);??

????DiskLruCache.Snapshot?snapShot?=?mDiskLruCache.get(key);??

????if?(snapShot?!=?null)?{??

????????InputStream?is?=?snapShot.getInputStream(0);??

????????Bitmap?bitmap?=?BitmapFactory.decodeStream(is);??

????????mImage.setImageBitmap(bitmap);??

????}??

}?catch?(IOException?e)?{??

????e.printStackTrace();??

}

?

我們使用了BitmapFactory的decodeStream()方法將文件流解析成Bitmap對(duì)象,然后把它設(shè)置到ImageView當(dāng)中。如果運(yùn)行一下程序,將會(huì)看到如下效果:

OK,圖片已經(jīng)成功顯示出來(lái)了。注意這是我們從本地緩存中加載的,而不是從網(wǎng)絡(luò)上加載的,因此即使在你手機(jī)沒(méi)有聯(lián)網(wǎng)的情況下,這張圖片仍然可以顯示出來(lái)。

移除緩存

學(xué)習(xí)完了寫入緩存和讀取緩存的方法之后,最難的兩個(gè)操作你就都已經(jīng)掌握了,那么接下來(lái)要學(xué)習(xí)的移除緩存對(duì)你來(lái)說(shuō)也一定非常輕松了。移除緩存主要是借助DiskLruCache的remove()方法實(shí)現(xiàn)的,接口如下所示:

1

public?synchronized?boolean?remove(String?key)?throws?IOException

相信你已經(jīng)相當(dāng)熟悉了,remove()方法中要求傳入一個(gè)key,然后會(huì)刪除這個(gè)key對(duì)應(yīng)的緩存圖片,示例代碼如下:

1

2

3

4

5

6

7

try?{??

????String?imageUrl?=?"http://img.21ic.com/21ic_pic/CSDN/=utf-8' '1378037235_7476.jpg";????

????String?key?=?hashKeyForDisk(imageUrl);????

????mDiskLruCache.remove(key);??

}?catch?(IOException?e)?{??

????e.printStackTrace();??

}

用法雖然簡(jiǎn)單,但是你要知道,這個(gè)方法我們并不應(yīng)該經(jīng)常去調(diào)用它。因?yàn)槟阃耆恍枰獡?dān)心緩存的數(shù)據(jù)過(guò)多從而占用SD卡太多空間的問(wèn)題,DiskLruCache會(huì)根據(jù)我們?cè)谡{(diào)用open()方法時(shí)設(shè)定的緩存最大值來(lái)自動(dòng)刪除多余的緩存。只有你確定某個(gè)key對(duì)應(yīng)的緩存內(nèi)容已經(jīng)過(guò)期,需要從網(wǎng)絡(luò)獲取最新數(shù)據(jù)的時(shí)候才應(yīng)該調(diào)用remove()方法來(lái)移除緩存。

其它API

除了寫入緩存、讀取緩存、移除緩存之外,DiskLruCache還提供了另外一些比較常用的API,我們簡(jiǎn)單學(xué)習(xí)一下。

1.?size()

這個(gè)方法會(huì)返回當(dāng)前緩存路徑下所有緩存數(shù)據(jù)的總字節(jié)數(shù),以byte為單位,如果應(yīng)用程序中需要在界面上顯示當(dāng)前緩存數(shù)據(jù)的總大小,就可以通過(guò)調(diào)用這個(gè)方法計(jì)算出來(lái)。比如網(wǎng)易新聞中就有這樣一個(gè)功能,如下圖所示:

2.flush()

這個(gè)方法用于將內(nèi)存中的操作記錄同步到日志文件(也就是journal文件)當(dāng)中。這個(gè)方法非常重要,因?yàn)镈iskLruCache能夠正常工作的前提就是要依賴于journal文件中的內(nèi)容。前面在講解寫入緩存操作的時(shí)候我有調(diào)用過(guò)一次這個(gè)方法,但其實(shí)并不是每次寫入緩存都要調(diào)用一次flush()方法的,頻繁地調(diào)用并不會(huì)帶來(lái)任何好處,只會(huì)額外增加同步j(luò)ournal文件的時(shí)間。比較標(biāo)準(zhǔn)的做法就是在Activity的onPause()方法中去調(diào)用一次flush()方法就可以了。

3.close()

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

4.delete()

這個(gè)方法用于將所有的緩存數(shù)據(jù)全部刪除,比如說(shuō)網(wǎng)易新聞中的那個(gè)手動(dòng)清理緩存功能,其實(shí)只需要調(diào)用一下DiskLruCache的delete()方法就可以實(shí)現(xiàn)了。



本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉