首選說下個人覺得網(wǎng)絡(luò)緩存控制的優(yōu)勢:
- 1.幫app端用戶減少流量消耗(因為很多情況下躬窜,請求網(wǎng)絡(luò)返回的response并沒有變化)执解,同時提升用戶體驗,可以在沒有網(wǎng)絡(luò)的情況下也可以查看上次的數(shù)據(jù);
- 2.根據(jù)業(yè)務(wù)場景渔彰,設(shè)置不同的緩存時間,app端的用戶體驗提高推正,穩(wěn)定性能提高恍涂;
- 3.通過減少很多不必要的http請求,減輕服務(wù)器負(fù)載植榕,同時也可以減少服務(wù)端消耗的數(shù)據(jù)流量再沧。
常用的緩存方式:
如果你的網(wǎng)路請求框架是Retrofit或OkHttpClient,那么只需要通過設(shè)置cache和Interceptor即可尊残,cache的作用是指定緩存文件地址炒瘸、大小淤堵,Interceptor稍微復(fù)雜一些,分為應(yīng)用攔截什燕、網(wǎng)絡(luò)攔截兩種粘勒,主要控制緩存的時間、方式屎即、過濾等庙睡。
具體通過代碼來講解:
if (retrofit == null) {
retrofit=new Retrofit.Builder().baseUrl("http://gank.io/api/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
//偷個懶直接寫一起
.client(new OkHttpClient.Builder()
.cache(new Cache(new File(context.getExternalCacheDir(),"test_cache"),10 * 1024 * 1024))
.addInterceptor(new CaheInterceptor(context))
.addNetworkInterceptor(new CaheInterceptor(context))
.connectTimeout(5, TimeUnit.SECONDS)
.build())
.build();
}
上述代碼就為retrofit單例添加了緩存機制,最大緩存空間為10Mb技俐,應(yīng)用攔截與網(wǎng)絡(luò)攔截也采用了同一個攔截器乘陪,簡單區(qū)別就是
addNetworkInterceptor添加的是網(wǎng)絡(luò)攔截器,他會在在request和resposne是分別被調(diào)用一次雕擂,
能夠操作中間過程的響應(yīng),如重定向和重試啡邑;
而addinterceptor添加的是aplication攔截器,他只會在response被調(diào)用一次井赌,
且總是只調(diào)用一次谤逼,不需要擔(dān)心中間過程的響應(yīng)。
Interceptor的具體實現(xiàn)也很簡單仇穗,只需要重寫一個intercept方法流部,在其中處理多種緩存狀態(tài),例有網(wǎng)絡(luò)纹坐,無網(wǎng)絡(luò)枝冀,網(wǎng)絡(luò)狀態(tài)差等等。
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (NetworkUtils.isNetworkAvailable(context)) {
Response response = chain.proceed(request);
// read from cache for 0 s 有網(wǎng)絡(luò)不會使用緩存數(shù)據(jù)
int maxAge = 10;
String cacheControl = request.cacheControl().toString();
return response.newBuilder()
.removeHeader("Pragma")
.removeHeader("Cache-Control")
.header("Cache-Control", "public, max-age=" + maxAge)
.build();
} else {
//無網(wǎng)絡(luò)時強制使用緩存數(shù)據(jù)
request = request.newBuilder()
.cacheControl(CacheControl.FORCE_CACHE)
.build();
Response response = chain.proceed(request);
//set cahe times ; value is useless at all !
// int maxStale = 60;
int maxStale = 60 * 60 * 24 * 3;
return response.newBuilder()
.removeHeader("Pragma")
.removeHeader("Cache-Control")
.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
.build();
}
}
上面的代碼僅根據(jù)當(dāng)前有無網(wǎng)絡(luò)耘子,對返回的數(shù)據(jù)response做了一個攔截處理果漾,其中需要注意的是
- removeHeader();去除相關(guān)Cache-Control(緩存控制)的HTTP頭信息谷誓,不用去管绒障,一般都是固定的格式;
- int maxAge = 10捍歪; 該值表示有網(wǎng)絡(luò)的時候户辱,希望在10S內(nèi)不去重新獲取網(wǎng)絡(luò)數(shù)據(jù),而是直接使用緩存數(shù)據(jù)费封;
- int maxStale = 60 * 60 * 24 * 3; 表示在無網(wǎng)絡(luò)的情況下,在3天內(nèi)使用緩存數(shù)據(jù)?但是在demo中實際調(diào)試發(fā)現(xiàn),該值并沒有什么軟用乔遮,即使你設(shè)置為0蚂踊,無網(wǎng)絡(luò)時也會使用緩存數(shù)據(jù)。原因在這里:
//無網(wǎng)絡(luò)時強制使用緩存數(shù)據(jù)
request = request.newBuilder()
.cacheControl(CacheControl.FORCE_CACHE)
.build();
追蹤CacheControl.FORCE_CACHE型的cacheControl源碼埃疫,發(fā)現(xiàn)其內(nèi)部帚湘,已經(jīng)將maxStale 設(shè)置為無限大了哮针。
public static final CacheControl FORCE_CACHE = new Builder()
.onlyIfCached()
.maxStale(Integer.MAX_VALUE, TimeUnit.SECONDS)
.build();
這樣锤窑,一個簡單的緩存方式就完成了璧针,看下demo效果,當(dāng)我在10S內(nèi)去不停地獲取Gank.io中圖片時渊啰,返回的一直是同一張探橱,僅當(dāng)超過設(shè)置的maxAge時間后,picurl才更新了:
04-14 16:32:27.858 21905-21905/com.blink.dagger.democache D/luck: pic url :http://ww2.sinaimg.cn/large/7a8aed7bgw1ewees6m58qj20dw0kuadj.jpg
04-14 16:32:27.860 21905-21905/com.blink.dagger.democache D/luck: current time :2017-04-14 16:32:27
04-14 16:32:29.989 21905-21905/com.blink.dagger.democache D/luck: pic url :http://ww2.sinaimg.cn/large/7a8aed7bgw1ewees6m58qj20dw0kuadj.jpg
04-14 16:32:29.991 21905-21905/com.blink.dagger.democache D/luck: current time :2017-04-14 16:32:29
04-14 16:32:31.098 21905-21905/com.blink.dagger.democache D/luck: pic url :http://ww2.sinaimg.cn/large/7a8aed7bgw1ewees6m58qj20dw0kuadj.jpg
04-14 16:32:31.099 21905-21905/com.blink.dagger.democache D/luck: current time :2017-04-14 16:32:31
04-14 16:32:32.481 21905-21905/com.blink.dagger.democache D/luck: pic url :http://ww2.sinaimg.cn/large/7a8aed7bgw1ewees6m58qj20dw0kuadj.jpg
04-14 16:32:32.482 21905-21905/com.blink.dagger.democache D/luck: current time :2017-04-14 16:32:32
04-14 16:32:34.327 21905-21905/com.blink.dagger.democache D/luck: pic url :http://ww2.sinaimg.cn/large/7a8aed7bgw1ewees6m58qj20dw0kuadj.jpg
04-14 16:32:34.328 21905-21905/com.blink.dagger.democache D/luck: current time :2017-04-14 16:32:34
04-14 16:32:36.865 21905-21905/com.blink.dagger.democache D/luck: pic url :http://ww1.sinaimg.cn/large/7a8aed7bjw1ezf3wrxcx2j20p011i7b2.jpg
04-14 16:32:36.867 21905-21905/com.blink.dagger.democache D/luck: current time :2017-04-14 16:32:36
而我們的手機ExternalCacheDir路徑下绘证,多了一些二進制文件隧膏,所以如果需要做一個清除緩存的功能,在業(yè)務(wù)代碼中delete file即可嚷那。
Cookie緩存:
一般的場景應(yīng)該都用不到這種緩存方式胞枕,僅在每一次請求訪問網(wǎng)絡(luò)的時候,需要根據(jù)url將Cookie中的緩存數(shù)據(jù)提交給后臺時才用的著魏宽。
使用方法:
.cookieJar(new NovateCookieManger(context))
而且要實現(xiàn)CookieJar非常麻煩:
- 1.首選需要根據(jù)httpurl保存/發(fā)送Cookie(實現(xiàn)CookieJar接口)腐泻;
- 2.將Map形式的cookies緩存至內(nèi)存中;
- 3.將cookies序列化后通過SP持久化至本地队询;
好在這種反人類的緩存方式一般不用派桩。
Cookie難以被緩存,且大多情境下是沒有必要的娘摔。如果你非得使用Cookie窄坦,建議用在動態(tài)頁面上。
具體的代碼太長了凳寺,這兒就不貼了鸭津,直接放在demo中了。