在网络请求中缓存占着非常重要的作用,不仅影响着用户体验也跟产品的使用流量有关,Okhttp框架提供了CacheInterceptor拦截器负责处理请求的缓存,CacheInterceptor会根据请求的内容和设置的缓存时间判断内容的有限期,在有效期内直接返回数据从而减少网络请求,下面具体分析CacheInterceptor拦截器
1、 CacheInterceptor:负责缓存管理
@Override public Response intercept(Chain chain) throws IOException {
Response cacheCandidate = cache != null
? cache.get(chain.request()) //(1)获取请求地址对应的缓存数据
: null;
long now = System.currentTimeMillis();
CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get(); //(2)封装请求信息和缓存信息,并判断能否使用缓存
Request networkRequest = strategy.networkRequest;
Response cacheResponse = strategy.cacheResponse;
if (cache != null) {
cache.trackResponse(strategy);
}
if (cacheCandidate != null && cacheResponse == null) {
//1、有缓存信息但不能使用,关闭缓存
closeQuietly(cacheCandidate.body());
}
if (networkRequest == null && cacheResponse == null) {
//2、禁止网络请求但缓存又不可用,直接返回504
return new Response.Builder()
.request(chain.request())
.protocol(Protocol.HTTP_1_1)
.code(504)
.message("Unsatisfiable Request (only-if-cached)")
.body(Util.EMPTY_RESPONSE)
.sentRequestAtMillis(-1L)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
}
if (networkRequest == null) {
//3、如果网络请求不可用,强制使用缓存信息
return cacheResponse.newBuilder()
.cacheResponse(stripBody(cacheResponse))
.build();
}
Response networkResponse = null;
try {
networkResponse = chain.proceed(networkRequest); //4、执行网络请求,请求远程资源
} finally {
if (networkResponse == null && cacheCandidate != null) {
closeQuietly(cacheCandidate.body());
}
}
if (cacheResponse != null) {
//在网络请求成功后,此时也有缓存信息,则响应以下操作
if (networkResponse.code() == HTTP_NOT_MODIFIED) {
//5、响应304返回缓存数据
Response response = cacheResponse.newBuilder()
.headers(combine(cacheResponse.headers(), networkResponse.headers()))
.sentRequestAtMillis(networkResponse.sentRequestAtMillis())
.receivedResponseAtMillis(networkResponse.receivedResponseAtMillis())
.cacheResponse(stripBody(cacheResponse))
.networkResponse(stripBody(networkResponse))
.build();
return response;
} else {
closeQuietly(cacheResponse.body());
}
}
Response response = networkResponse.newBuilder() //6、使用请求的最新数据
.cacheResponse(stripBody(cacheResponse))
.networkResponse