日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

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

下載

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

打開緩存

這樣的話我們就把準備工作做好了,下面看一下DiskLruCache到底該如何使用。首先你要知道,DiskLruCache是不能new出實例的,如果我們要創(chuàng)建一個DiskLruCache的實例,則需要調(diào)用它的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ù)。

其中緩存地址前面已經(jīng)說過了,通常都會存放在?/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卡不可被移除的時候,就調(diào)用getExternalCacheDir()方法來獲取緩存路徑,否則就調(diào)用getCacheDir()方法來獲取緩存路徑。前者獲取到的就是?/sdcard/Android/data/

接著又將獲取到的路徑和一個uniqueName進行拼接,作為最終的緩存路徑返回。那么這個uniqueName又是什么呢?其實這就是為了對不同類型的數(shù)據(jù)進行區(qū)分而設定的一個唯一值,比如說在網(wǎng)易新聞緩存路徑下看到的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ù)都應該從網(wǎng)上重新獲取。

后面兩個參數(shù)就沒什么需要解釋的了,第三個參數(shù)傳1,第四個參數(shù)通常傳入10M的大小就夠了,這個可以根據(jù)自身的情況進行調(diào)節(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();??

}

首先調(diào)用getDiskCacheDir()方法獲取到緩存地址的路徑,然后判斷一下該路徑是否存在,如果不存在就創(chuàng)建一下。接著調(diào)用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中傳入的網(wǎng)址,并通過outputStream寫入到本地。有了這個方法之后,下面我們就可以使用DiskLruCache來進行寫入了,寫入的操作是借助DiskLruCache.Editor這個類完成的。類似地,這個類也是不能new的,需要調(diào)用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)在我們只需要調(diào)用一下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的實例之后,我們可以調(diào)用它的newOutputStream()方法來創(chuàng)建一個輸出流,然后把它傳入到downloadUrlToStream()中就能實現(xiàn)下載并寫入緩存的功能了。注意newOutputStream()方法接收一個index參數(shù),由于前面在設置valueCount的時候指定的是1,所以這里index傳0就可以了。在寫入操作執(zhí)行完之后,我們還需要調(diào)用一下commit()方法進行提交才能使寫入生效,調(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()方法來從網(wǎng)絡上下載圖片,所以一定要確保這段代碼是在子線程當中執(zhí)行的。注意在代碼的最后我還調(diào)用了一下flush()方法,這個方法并不是每次寫入都必須要調(diào)用的,但在這里卻不可缺少,我會在后面說明它的作用。

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

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

讀取緩存

緩存已經(jīng)寫入成功之后,接下來我們就該學習一下如何讀取了。讀取的方法要比寫入簡單一些,主要是借助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對象,這個對象我們該怎么利用呢?很簡單,只需要調(diào)用它的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,圖片已經(jīng)成功顯示出來了。注意這是我們從本地緩存中加載的,而不是從網(wǎng)絡上加載的,因此即使在你手機沒有聯(lián)網(wǎng)的情況下,這張圖片仍然可以顯示出來。

移除緩存

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

1

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

相信你已經(jīng)相當熟悉了,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();??

}

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

其它API

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

1.?size()

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

2.flush()

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

3.close()

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

4.delete()

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



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