Androi App缓存管理
轉(zhuǎn)自:http://www.cnblogs.com/qianxudetianxia/archive/2012/02/20/2112128.html
無(wú)論大型或小型應(yīng)用,靈活的緩存可以說不僅大大減輕了服務(wù)器的壓力,而且因?yàn)楦焖俚挠脩趔w驗(yàn)而方便了用戶。
Android的apk可以說是作為小型應(yīng)用,其中99%的應(yīng)用并不是需要實(shí)時(shí)更新的,而且詬病于蝸牛般的移動(dòng)網(wǎng)速,與服務(wù)器的數(shù)據(jù)交互是能少則少,這樣用戶體驗(yàn)才更好,這也是我們有時(shí)舍棄webview而采用json傳輸數(shù)據(jù)的原因之一。?
采用緩存,可以進(jìn)一步大大緩解數(shù)據(jù)交互的壓力,特此,我們簡(jiǎn)略列舉一下緩存管理的適用環(huán)境:
1. 提供網(wǎng)絡(luò)服務(wù)的應(yīng)用
2. 數(shù)據(jù)更新不需要實(shí)時(shí)更新,但是哪怕是3-5分鐘的延遲也是可以采用緩存機(jī)制。?
3. 緩存的過期時(shí)間是可以接受的(不會(huì)因?yàn)榫彺鎺?lái)的好處,導(dǎo)致某些數(shù)據(jù)因?yàn)楦虏患皶r(shí)而影響產(chǎn)品的形象等)
帶來(lái)的好處:
1. 服務(wù)器的壓力大大減小
2. 客戶端的響應(yīng)速度大大變快(用戶體驗(yàn))
3. 客戶端的數(shù)據(jù)加載出錯(cuò)情況大大較少,大大提高了應(yīng)有的穩(wěn)定性(用戶體驗(yàn))
4. 一定程度上可以支持離線瀏覽(或者說為離線瀏覽提供了技術(shù)支持)
一、緩存管理的方法
這里的緩存管理的原理很簡(jiǎn):通過時(shí)間的設(shè)置來(lái)判斷是否讀取緩存還是重新下載。
里面會(huì)有一些細(xì)節(jié)的處理,后面會(huì)詳細(xì)闡述。
基于這個(gè)原理,目前鄙人見過的兩種比較常見的緩存管理方法是:數(shù)據(jù)庫(kù)法和文件法。
二、數(shù)據(jù)庫(kù)法緩存管理
這種方法是在下載完數(shù)據(jù)文件后,把文件的相關(guān)信息如url,路經(jīng),下載時(shí)間,過期時(shí)間等存放到數(shù)據(jù)庫(kù),下次下載的時(shí)候根據(jù)url先從數(shù)據(jù)庫(kù)中查詢,如果查詢到當(dāng)前時(shí)間并未過期,就根據(jù)路徑讀取本地文件,從而實(shí)現(xiàn)緩存的效果。
從實(shí)現(xiàn)上我們可以看到這種方法可以靈活存放文件的屬性,進(jìn)而提供了很大的擴(kuò)展性,可以為其它的功能提供一定的支持;
從操作上需要?jiǎng)?chuàng)建數(shù)據(jù)庫(kù),每次查詢數(shù)據(jù)庫(kù),如果過期還需要更新數(shù)據(jù)庫(kù),清理緩存的時(shí)候還需要?jiǎng)h除數(shù)據(jù)庫(kù)數(shù)據(jù),稍顯麻煩,而數(shù)據(jù)庫(kù)操作不當(dāng)又容易出現(xiàn)一系列的性能,ANR問題,實(shí)現(xiàn)的時(shí)候要謹(jǐn)慎,具體作的話,但也只是增加一個(gè)工具類或方法的事情。
還有一個(gè)問題,緩存的數(shù)據(jù)庫(kù)是存放在/data/data/<package>/databases/目錄下,是占用內(nèi)存空間的,如果緩存累計(jì),容易浪費(fèi)內(nèi)存,需要及時(shí)清理緩存。
當(dāng)然這種方法從目前一些應(yīng)用的實(shí)用上看,我沒有發(fā)現(xiàn)什么問題。
本文我側(cè)重強(qiáng)調(diào)第二種方法,第一種方法的實(shí)現(xiàn),就此掠過。?
三、文件法緩存管理
這種方法,使用File.lastModified()方法得到文件的最后修改時(shí)間,與當(dāng)前時(shí)間判斷是否過期,從而實(shí)現(xiàn)緩存效果。
實(shí)現(xiàn)上只能使用這一個(gè)屬性,沒有為其它的功能提供技術(shù)支持的可能。
操作上倒是簡(jiǎn)單,比較時(shí)間即可。本身處理也不容易帶來(lái)其它問題,代價(jià)低廉。
四、文件法緩存管理的兩點(diǎn)說明
1. 不同類型的文件的緩存時(shí)間不一樣。
籠統(tǒng)的說,不變文件的緩存時(shí)間是永久,變化文件的緩存時(shí)間是最大忍受不變時(shí)間。
說白點(diǎn),圖片文件內(nèi)容是不變的,直到清理,我們是可以永遠(yuǎn)讀取緩存的。
配置文件內(nèi)容是可能更新的,需要設(shè)置一個(gè)可接受的緩存時(shí)間。
2. 不同環(huán)境下的緩存時(shí)間標(biāo)準(zhǔn)不一樣。
無(wú)網(wǎng)絡(luò)環(huán)境下,我們只能讀取緩存文件,哪怕緩存早就過期。
WiFi網(wǎng)絡(luò)環(huán)境下,緩存時(shí)間可以設(shè)置短一點(diǎn),一是網(wǎng)速較快,而是流量不要錢。
移動(dòng)數(shù)據(jù)流量環(huán)境下,緩存時(shí)間可以設(shè)置長(zhǎng)一點(diǎn),節(jié)省流量,就是節(jié)省金錢,而且用戶體驗(yàn)也更好。
舉個(gè)例子吧,最近本人在做的一個(gè)應(yīng)用在wifi環(huán)境下的緩存時(shí)間設(shè)置為5分鐘,移動(dòng)數(shù)據(jù)流量下的緩存時(shí)間設(shè)置為1小時(shí)。
這個(gè)時(shí)間根據(jù)自己的實(shí)際情況來(lái)設(shè)置:數(shù)據(jù)的更新頻率,數(shù)據(jù)的重要性等。
五、何時(shí)刷新
開發(fā)者一方面希望盡量讀取緩存,用戶一方面希望實(shí)時(shí)刷新,但是響應(yīng)速度越快越好,流量消耗越少越好,是一個(gè)矛盾。
其實(shí)何時(shí)刷新我也不知道,這里我提供兩點(diǎn)建議:
1. 數(shù)據(jù)的最長(zhǎng)多長(zhǎng)時(shí)間不變,對(duì)應(yīng)用無(wú)大的影響。
比如,你的數(shù)據(jù)更新時(shí)間為1天,則緩存時(shí)間設(shè)置為4~8小時(shí)比較合適,一天他總會(huì)看到更新,如果你覺得你是資訊類應(yīng)用,再減少,2~4小時(shí),如果你覺得數(shù)據(jù)比較重要或者比較受歡迎,用戶會(huì)經(jīng)常把玩,再減少,1~2小時(shí),依次類推。
為了保險(xiǎn)起見,你可能需要毫無(wú)理由的再次縮減一下。
2. 提供刷新按鈕。
上面說的保險(xiǎn)起見不一定保險(xiǎn),最保險(xiǎn)的方法使在相關(guān)界面提供一個(gè)刷新按鈕,為緩存,為加載失敗提供一次重新來(lái)過的機(jī)會(huì),有了這個(gè)刷新按鈕,我們的心也才真的放下來(lái)。
六、文件緩存法的具體實(shí)現(xiàn)
針對(duì)配置文件的緩存,我新建了一個(gè)類ConfigCache:
| 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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | import?java.io.File; import?java.io.IOException; import?android.util.Log; import?com.tianxia.app.floworld.AppApplication; import?com.tianxia.app.floworld.utils.FileUtils; import?com.tianxia.app.floworld.utils.NetworkUtils; public?class?ConfigCache { ????private?static?final?String TAG = ConfigCache.class.getName(); ????public?static?final?int?CONFIG_CACHE_MOBILE_TIMEOUT? =?3600000;??//1 hour ????public?static?final?int?CONFIG_CACHE_WIFI_TIMEOUT??? =?300000;???//5 minute ????public?static?String getUrlCache(String url) { ????????if?(url ==?null) { ????????????return?null; ????????} ????????String result =?null; ????????File file =?new?File(AppApplication.mSdcardDataDir +?"/"?+ getCacheDecodeString(url)); ????????if?(file.exists() && file.isFile()) { ????????????long?expiredTime = System.currentTimeMillis() - file.lastModified(); ????????????Log.d(TAG, file.getAbsolutePath() +?" expiredTime:"?+ expiredTime/60000?+?"min"); ????????????//1. in case the system time is incorrect (the time is turn back long ago) ????????????//2. when the network is invalid, you can only read the cache ????????????if?(AppApplication.mNetWorkState != NetworkUtils.NETWORN_NONE && expiredTime <?0) { ????????????????return?null; ????????????} ????????????if(AppApplication.mNetWorkState == NetworkUtils.NETWORN_WIFI ???????????????????&& expiredTime > CONFIG_CACHE_WIFI_TIMEOUT) { ????????????????return?null; ????????????}?else?if?(AppApplication.mNetWorkState == NetworkUtils.NETWORN_MOBILE ???????????????????&& expiredTime > CONFIG_CACHE_MOBILE_TIMEOUT) { ????????????????return?null; ????????????} ????????????try?{ ????????????????result = FileUtils.readTextFile(file); ????????????}?catch?(IOException e) { ????????????????e.printStackTrace(); ????????????} ????????} ????????return?result; ????} ????public?static?void?setUrlCache(String data, String url) { ????????File file =?new?File(AppApplication.mSdcardDataDir +?"/"?+ getCacheDecodeString(url)); ????????try?{ ????????????//創(chuàng)建緩存數(shù)據(jù)到磁盤,就是創(chuàng)建文件 ????????????FileUtils.writeTextFile(file, data); ????????}?catch?(IOException e) { ????????????Log.d(TAG,?"write "?+ file.getAbsolutePath() +?" data failed!"); ????????????e.printStackTrace(); ????????} ????} ????public?static?String getCacheDecodeString(String url) { ????????//1. 處理特殊字符 ????????//2. 去除后綴名帶來(lái)的文件瀏覽器的視圖凌亂(特別是圖片更需要如此類似處理,否則有的手機(jī)打開圖庫(kù),全是我們的緩存圖片) ????????if?(url !=?null) { ????????????return?url.replaceAll("[.:/,%?&=]",?"+").replaceAll("[+]+",?"+"); ????????} ????????return?null; ????} } |
? ? ? 從實(shí)現(xiàn)上我們?nèi)婵紤]了幾個(gè)細(xì)節(jié),注釋已經(jīng)說明,不再贅述。
? ? ? 然后我們調(diào)用方法如下:
| 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 | void?getConfig(){ ????????//首先嘗試讀取緩存 ????????String cacheConfigString = ConfigCache.getUrlCache(CONFIG_URL); ????????//根據(jù)結(jié)果判定是讀取緩存,還是重新讀取 ????????if?(cacheConfigString !=?null) { ????????????showConfig(cacheConfigString); ????????}?else?{ ????????????//如果緩存結(jié)果是空,說明需要重新加載 ????????????//緩存為空的原因可能是1.無(wú)緩存;2. 緩存過期;3.讀取緩存出錯(cuò) ????????????AsyncHttpClient client =?new?AsyncHttpClient(); ????????????client.get(CONFIG_URL,?new?AsyncHttpResponseHandler(){ ????????????????@Override ????????????????public?void?onSuccess(String result){ ????????????????????//成功下載,則保存到本地作為后面緩存文件 ????????????????????ConfigCache.setUrlCache(result,? CONFIG_URL); ????????????????????//后面可以是UI更新,僅供參考 ????????????????????showConfig(result); ????????????????} ????????????????@Override ????????????????public?void?onFailure(Throwable arg0) { ????????????????????//根據(jù)失敗原因,考慮是顯示加載失敗,還是再讀取緩存 ????????????????} ????????????}); ????????} ????} |
這樣配置文件既能有效緩存,又能及時(shí)更新了,同時(shí)支持離線瀏覽。
七、小結(jié)
? ? ?智能手機(jī)的緩存管理應(yīng)用非常的普遍和需要,是提高用戶體驗(yàn)的有效手段之一。
? ? ?當(dāng)然,緩存管理一些內(nèi)容沒有細(xì)說,如圖片緩存,緩存清理等,這些處理起來(lái)比較簡(jiǎn)單。?
總結(jié)
以上是生活随笔為你收集整理的Androi App缓存管理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android闹钟 AlarmManag
- 下一篇: Kotlin学习笔记(1)- 环境配置