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

當前位置:首頁 > > 充電吧
[導讀]下載好了,對DiskLruCache有了最初的認識之后,下面我們來學習一下DiskLruCache的用法吧。由于DiskLruCache并不是由Google官方編寫的,所以這個類并沒有被包含在Andr

下載

好了,對DiskLruCache有了最初的認識之后,下面我們來學習一下DiskLruCache的用法吧。由于DiskLruCache并不是由Google官方編寫的,所以這個類并沒有被包含在Android?API當中,我們需要將這個類從網上下載下來,然后手動添加到項目當中。DiskLruCache的源碼在Google?Source上,地址在文章底部,下載好了源碼之后,只需要在項目中新建一個libcore.io包,然后將DiskLruCache.java文件復制到這個包中即可。

打開緩存

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

1

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

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

其中緩存地址前面已經說過了,通常都會存放在?/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);??

}

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

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

接著是應用程序版本號,我們可以使用如下代碼簡單地獲取到當前應用程序的版本號:

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

}

需要注意的是,每當版本號改變,緩存路徑下存儲的所有數(shù)據(jù)都會被清除掉,因為DiskLruCache認為當應用程序有版本更新的時候,所有的數(shù)據(jù)都應該從網上重新獲取。

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

因此,一個非常標準的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();??

}

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

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

寫入緩存

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

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

}

這段代碼相當基礎,相信大家都看得懂,就是訪問urlString中傳入的網址,并通過outputStream寫入到本地。有了這個方法之后,下面我們就可以使用DiskLruCache來進行寫入了,寫入的操作是借助DiskLruCache.Editor這個類完成的。類似地,這個類也是不能new的,需要調用DiskLruCache的edit()方法來獲取實例,接口如下所示:

雙擊代碼復制

1

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

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

那么我們就寫一個方法用來將字符串進行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();??

}

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

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

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的實例之后,我們可以調用它的newOutputStream()方法來創(chuàng)建一個輸出流,然后把它傳入到downloadUrlToStream()中就能實現(xiàn)下載并寫入緩存的功能了。注意newOutputStream()方法接收一個index參數(shù),由于前面在設置valueCount的時候指定的是1,所以這里index傳0就可以了。在寫入操作執(zhí)行完之后,我們還需要調用一下commit()方法進行提交才能使寫入生效,調用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();

由于這里調用了downloadUrlToStream()方法來從網絡上下載圖片,所以一定要確保這段代碼是在子線程當中執(zhí)行的。注意在代碼的最后我還調用了一下flush()方法,這個方法并不是每次寫入都必須要調用的,但在這里卻不可缺少,我會在后面說明它的作用。

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

可以看到,這里有一個文件名很長的文件,和一個journal文件,那個文件名很長的文件自然就是緩存的圖片了,因為是使用了MD5編碼來進行命名的。

讀取緩存

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

1

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

很明顯,get()方法要求傳入一個key來獲取到相應的緩存數(shù)據(jù),而這個key毫無疑問就是將圖片URL進行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);

很奇怪的是,這里獲取到的是一個DiskLruCache.Snapshot對象,這個對象我們該怎么利用呢?很簡單,只需要調用它的getInputStream()方法就可以得到緩存文件的輸入流了。同樣地,getInputStream()方法也需要傳一個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對象,然后把它設置到ImageView當中。如果運行一下程序,將會看到如下效果:

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

移除緩存

學習完了寫入緩存和讀取緩存的方法之后,最難的兩個操作你就都已經掌握了,那么接下來要學習的移除緩存對你來說也一定非常輕松了。移除緩存主要是借助DiskLruCache的remove()方法實現(xiàn)的,接口如下所示:

1

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

相信你已經相當熟悉了,remove()方法中要求傳入一個key,然后會刪除這個key對應的緩存圖片,示例代碼如下:

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

}

用法雖然簡單,但是你要知道,這個方法我們并不應該經常去調用它。因為你完全不需要擔心緩存的數(shù)據(jù)過多從而占用SD卡太多空間的問題,DiskLruCache會根據(jù)我們在調用open()方法時設定的緩存最大值來自動刪除多余的緩存。只有你確定某個key對應的緩存內容已經過期,需要從網絡獲取最新數(shù)據(jù)的時候才應該調用remove()方法來移除緩存。

其它API

除了寫入緩存、讀取緩存、移除緩存之外,DiskLruCache還提供了另外一些比較常用的API,我們簡單學習一下。

1.?size()

這個方法會返回當前緩存路徑下所有緩存數(shù)據(jù)的總字節(jié)數(shù),以byte為單位,如果應用程序中需要在界面上顯示當前緩存數(shù)據(jù)的總大小,就可以通過調用這個方法計算出來。比如網易新聞中就有這樣一個功能,如下圖所示:

2.flush()

這個方法用于將內存中的操作記錄同步到日志文件(也就是journal文件)當中。這個方法非常重要,因為DiskLruCache能夠正常工作的前提就是要依賴于journal文件中的內容。前面在講解寫入緩存操作的時候我有調用過一次這個方法,但其實并不是每次寫入緩存都要調用一次flush()方法的,頻繁地調用并不會帶來任何好處,只會額外增加同步journal文件的時間。比較標準的做法就是在Activity的onPause()方法中去調用一次flush()方法就可以了。

3.close()

這個方法用于將DiskLruCache關閉掉,是和open()方法對應的一個方法。關閉掉了之后就不能再調用DiskLruCache中任何操作緩存數(shù)據(jù)的方法,通常只應該在Activity的onDestroy()方法中去調用close()方法。

4.delete()

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



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

LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: 驅動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設備,其驅動電源的性能直接關系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅動電源設計中至關重要的兩個環(huán)節(jié),集成化方案的設計成為提升電機驅動性能的關鍵。

關鍵字: 工業(yè)電機 驅動電源

LED 驅動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設備的使用壽命。然而,在實際應用中,LED 驅動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設計、生...

關鍵字: 驅動電源 照明系統(tǒng) 散熱

根據(jù)LED驅動電源的公式,電感內電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關鍵字: LED 設計 驅動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產業(yè)的重要發(fā)展方向。電動汽車的核心技術之一是電機驅動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅動系統(tǒng)中的關鍵元件,其性能直接影響到電動汽車的動力性能和...

關鍵字: 電動汽車 新能源 驅動電源

在現(xiàn)代城市建設中,街道及停車場照明作為基礎設施的重要組成部分,其質量和效率直接關系到城市的公共安全、居民生活質量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關鍵字: 發(fā)光二極管 驅動電源 LED

LED通用照明設計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關鍵字: LED 驅動電源 功率因數(shù)校正

在LED照明技術日益普及的今天,LED驅動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關鍵字: LED照明技術 電磁干擾 驅動電源

開關電源具有效率高的特性,而且開關電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅動電源

關鍵字: LED 驅動電源 開關電源

LED驅動電源是把電源供應轉換為特定的電壓電流以驅動LED發(fā)光的電壓轉換器,通常情況下:LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: LED 隧道燈 驅動電源
關閉