一.簡介
ASimpleCache只能作為一份教程,一個學習樣板,不能當真把它當回事。
作者楊福海,Afinal框架也是他創造的。
可是我讀ASimpleCache的900行代碼時,發現各種難看,並且都是很低級的缺點。我看的代碼是從github上下的,大概是2013年寫的,兩三年沒動了。可是網上為啥那么多關於ASimpleCache的文章,大概是因為它比較短比較能說明緩存的原理吧。
二.代碼缺點舉例
比如拼寫錯誤,明明是getDateInfoFromData()卻寫成了getDateFromDate(),雖然不太重要,但看的好難受有沒有。
private static String[] getDateInfoFromDate(byte[] data) { if (hasDateInfo(data)) { String saveDate = new String(copyOfRange(data, 0, 13)); String deleteAfter = new String( copyOfRange(data, 14, indexOf(data, mSeparator))); return new String[]{saveDate, deleteAfter}; } return null;
再比如字符串拼接問題,這個函數的作用是從文件中讀取字符串,因為反復用到字符串拼接,用StringBuilder總沒錯吧,可是代碼中用的是String,這就叫我怎能放心去用它。
public String getAsString(String key) { File file = mCache.get(key); if (!file.exists()) return null; boolean removeFile = false; BufferedReader in = null; try { in = new BufferedReader(new FileReader(file)); String readString = ""; String currentLine; while ((currentLine = in.readLine()) != null) { readString += currentLine; } if (!Utils.isDue(readString)) { return Utils.clearDateInfo(readString); } else { removeFile = true; return null; } } catch (IOException e) { e.printStackTrace(); return null; } finally { if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } if (removeFile) remove(key); } }
三.原理概述
緩存的當然是鍵值對!這個鍵值對不能存在內存里,否則應用程序終止之后,鍵值對就丟了。於是你說,那就程序關閉之前從內存里保存到磁盤不久完了。我說不行,因為程序可能非正常退出,那樣鍵值對不就全丟了,太不穩定了。所以,既然是緩存就要把一切信息存到磁盤上去。
鍵就是文件名,值當然就是文件內容了。凡是緩存,必有如下幾個特性:
- 會過期,當然也可能是永遠不過期,這過期時間,也應該放在磁盤上,等下次命中時,檢測是否過期
- 不重要,願刪就刪,頂多費點力氣重新下載
ASimpleCache把過期時間存到了文件內容中,前4個字節表示一個int,用來表示保質期秒數。
既然是文件,那就太簡單了,不僅可以存字符串,還可以存二進制。這么一來,再對它封裝一下,就可以直接緩存圖片Bitmap和drawable,serializable和jsonObject了,他們只是一個馬甲。
緩存太多了怎么辦,把舊的刪除。怎么算緩存太多?第一,緩存的條目(也就是鍵的個數)不能太多;第二,緩存的文件總大小不能太大,也就是文件夾的大小不能太大。用一個CacheManager來維護,當應用程序啟動時,根據文件夾下的文件個數和文件夾大小來初始化這個CacheManager,當往緩存中put時,就先檢測大小,若超過了,那就刪一點再存。CacheManager還有一個作用,維護一個hashMap用於快速定位鍵值對,也是在應用啟動時進行初始化。
存到哪里去?在android中,每一個Context都有一個getCacheDir()函數,返回的是一個文件夾,都緩存到這里去就行了。
查找時,根據key確定文件名,去cache目錄下找到文件並讀取全部字符串,其中這些字符串中包含着saveTime,也就是緩存的保質期。當調用get()函數獲取內容時,如果發現過期了,那就不能再用它了,就把這個文件刪掉,同時更改CacheManager的緩存個數及緩存大小(如果緩存太大了,就會按照最近最少使用原則刪掉舊文件),如你所知,當關閉應用程序並再次啟動時,需要遍歷cache目錄來初始化CacheManager。