緩存第一步就是要保存 response 數(shù)據(jù)到緩存文件中齿尽,oktthp 用的是 DiskLruCache 會(huì)緩存到文件中鬼吵。
cache.png
// 緩存路徑- app 緩存目錄
File file = new File(getCacheDir(), "bbb");
Cache cache = new Cache(file,
10 * 1024 * 1024); // 10 MB
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
// 緩存 10 秒
CacheControl cacheControl = new CacheControl.Builder()
.maxAge(10, TimeUnit.SECONDS)
.build();
return response.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control", cacheControl.toString())
.build();
}
})
.cache(cache);
通過(guò) addNetworkInterceptor 添加網(wǎng)絡(luò)攔截器修改 response 設(shè)置 cacheControl项炼,cacheControl 頭部就是服務(wù)器告訴瀏覽器緩存的規(guī)則揭厚。這里通過(guò) maxAge 參數(shù)設(shè)置緩存最大 10 秒內(nèi)有效但绕。
如果要實(shí)現(xiàn)無(wú)網(wǎng)絡(luò)時(shí)從緩存讀染却蕖(如果有的話)惶看,有網(wǎng)絡(luò)時(shí)緩存 10 秒怎么做?六孵?纬黎?
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (!isNetworkConnected()) {
// 無(wú)網(wǎng)絡(luò)時(shí)強(qiáng)制從緩存讀取,如果緩存中沒有數(shù)據(jù)會(huì)返回 504
// FORCE_CACHE 里設(shè)置了 only-if-cached=true 和 maxStale
// only-if-cached 顧名思義就是只有緩存中有數(shù)據(jù)才返回劫窒,沒有時(shí)返回 504
// maxStale 指可以取過(guò)期多久的數(shù)據(jù)本今,F(xiàn)ORCE_CACHE 中設(shè)置為了Int最大值
request = request.newBuilder()
.cacheControl(CacheControl.FORCE_CACHE)
.build();
}
return chain.proceed(request);
}
})
.addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
// 緩存 10 秒
CacheControl cacheControl = new CacheControl.Builder()
.maxAge(10, TimeUnit.SECONDS)
.build();
return response.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control", cacheControl.toString())
.build();
}
})
.cache(cache);
網(wǎng)絡(luò)緩存那不用動(dòng),通過(guò) addInterceptor 添加攔截器判斷是否有網(wǎng)絡(luò)主巍,沒有網(wǎng)絡(luò)時(shí)修改 request 添加 CacheControl.FORCE_CACHE 強(qiáng)制客戶端從緩存中讀取
如果要求無(wú)網(wǎng)絡(luò)時(shí)從緩存讀裙谙ⅰ(如果有的話),有網(wǎng)絡(luò)時(shí)從網(wǎng)絡(luò)獲取怎么做孕索?铐达?只需要在網(wǎng)絡(luò)判斷那簡(jiǎn)單修改就可以
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (!isNetworkConnected()) {
// 無(wú)網(wǎng)絡(luò)時(shí)強(qiáng)制從緩存讀取,如果緩存中沒有數(shù)據(jù)會(huì)返回 504
// FORCE_CACHE 里設(shè)置了 only-if-cached==true 和 maxStale
// only-if-cached 顧名思義就是只有緩存中有數(shù)據(jù)才返回檬果,沒有時(shí)返回 504
// maxStale 指可以取過(guò)期多久的數(shù)據(jù),F(xiàn)ORCE_CACHE 中設(shè)置為了Int最大值
request = request.newBuilder()
.cacheControl(CacheControl.FORCE_CACHE)
.build();
} else {
// 有網(wǎng)絡(luò)時(shí)從網(wǎng)絡(luò)獲取
// FORCE_NETWORK 里設(shè)置了 no-cache
// no-cache 顧名思義唐断,強(qiáng)制客戶端直接向服務(wù)器發(fā)送請(qǐng)求,也就是說(shuō)每次請(qǐng)求都必須向服務(wù)器發(fā)送选脊。服務(wù)器接收到請(qǐng)求,然后判斷資源是否變更脸甘,是則返回新內(nèi)容恳啥,否則返回304(Not Modified)。
// 注意服務(wù)器根據(jù) Etag 判斷資源未變更時(shí)返回的是 304丹诀,這時(shí)還是從緩存中拿钝的,這里有點(diǎn)違背 no-cache 的含義,要注意理解铆遭。
request = request.newBuilder()
.cacheControl(CacheControl.FORCE_NETWORK)
.build();
}
return chain.proceed(request);
}
})
.addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
// 緩存 10 秒
CacheControl cacheControl = new CacheControl.Builder()
.maxAge(10, TimeUnit.SECONDS)
.build();
return response.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control", cacheControl.toString())
.build();
}
})
.cache(cache);
boolean isNetworkConnected() {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
return networkInfo != null && networkInfo.isConnected();
}