要想清楚的了解可以三个类去了解
1.从 InternalCache 缓存类开始 然后只是一个接口 OkHttpClient 已经用Cache类 实现了
使用:
File externalStorageDirectory = Environment.getExternalStorageDirectory(); File cache = new File(externalStorageDirectory, "cache"); okHttpClient = new OkHttpClient.Builder() .cache(new Cache(cache, 1024 * 1024)) .build();Cache 类都做了什么呢:
Cache(File directory, long maxSize, FileSystem fileSystem) { this.cache = DiskLruCache.create(fileSystem, directory, VERSION, ENTRY_COUNT, maxSize); }
看到DiskLruCache 是不是很熟,就是使用这个对response 进行缓存的,并在里面用静态代理模式实现 InternalCache接口 .
2.CacheStrategy 缓存策略类 get()方法:
public CacheStrategy get() { CacheStrategy candidate = getCandidate(); if (candidate.networkRequest != null && request.cacheControl().onlyIfCached()) { // We're forbidden from using the network and the cache is insufficient. return new CacheStrategy(null, null); //必须从缓存中读取 } return candidate; }逻辑都在getCandidate()方法中作用:判断request 是否要网络请求,计算 response cache 是否过期,上面都不返回判断是否添加请求头再次做网络请求.
3.最后就是自身intercept方法了:
@Override public Response intercept(Chain chain) throws IOException {
Response cacheCandidate = cache != null
? cache.get(chain.request()) // url为 key取出缓存
: null;
long now = System.currentTimeMillis();
CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get();//创建缓存策略类,
做出是否需要网络的决定(从返回值去判定)
Request networkRequest = strategy.networkRequest;
Response cacheResponse = strategy.cacheResponse;
if (cache != null) {
cache.trackResponse(strategy);
}
//可能需要网络请求或者cacheResponse 没有过期
if (cacheCandidate != null && cacheResponse == null) {
closeQuietly(cacheCandidate.body()); // The cache candidate wasn't applicable. Close it.
}
// If we're forbidden from using the network and the cache is insufficient, fail.
if (networkRequest == null && cacheResponse == null) {
return new Response.Builder()
.request(chain.request()) //不能网络请求和从缓存中读取,将返回504响应吗
.protocol(Protocol.HTTP_1_1)
.code(504)
.message("Unsatisfiable Request (only-if-cached)")
.body(Util.EMPTY_RESPONSE)
.sentRequestAtMillis(-1L)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
}
// If we don't need the network, we're done.
if (networkRequest == null) { //返回有四种 1都为null(上面已经处理了),2.都为notnull 3.一个为Null 另一个为notnull
4.跟3反过来
return cacheResponse.newBuilder()
.cacheResponse(stripBody(cacheResponse)) //不需要网络请求返回缓存数据
.build();
}
Response networkResponse = null;
try {
networkResponse = chain.proceed(networkRequest); //调用一下拦截器
} finally {
// If we're crashing on I/O or otherwise, don't leak the cache body.
if (networkResponse == null && cacheCandidate != null) {
closeQuietly(cacheCandidate.body());
}
}
// If we have a cache response too, then we're doing a conditional get.
if (cacheResponse != null) {
if (networkResponse.code() == HTTP_NOT_MODIFIED) { //304 客户端已缓存标记
Response response = cacheResponse.newBuilder()
.headers(combine(cacheResponse.headers(), networkResponse.headers())) //合并响应头 因为放在 Arraylist
中,重复会覆盖掉
.sentRequestAtMillis(networkResponse.sentRequestAtMillis())
.receivedResponseAtMillis(networkResponse.receivedResponseAtMillis())
.cacheResponse(stripBody(cacheResponse))
.networkResponse(stripBody(networkResponse))
.build();
networkResponse.body().close();
// Update the cache after combining headers but before stripping the
// Content-Encoding header (as performed by initContentStream()).
cache.trackConditionalCacheHit();
cache.update(cacheResponse, response); //更新缓存数据
return response;
} else {
closeQuietly(cacheResponse.body());
}
}
Response response = networkResponse.newBuilder()
.cacheResponse(stripBody(cacheResponse))
.networkResponse(stripBody(networkResponse))
.build();
if (cache != null) {
//判断是否有响应体 和是否能缓存
if (HttpHeaders.hasBody(response) && CacheStrategy.isCacheable(response, networkRequest)) {
// Offer this request to the cache.
CacheRequest cacheRequest = cache.put(response); //放入缓存中
return cacheWritingResponse(cacheRequest, response);
}
if (HttpMethod.invalidatesCache(networkRequest.method())) { //默认支持get 不是get 将从缓存中移除
try {
cache.remove(networkRequest);
} catch (IOException ignored) {
// The cache cannot be written.
}
}
}
return response;
}
.最后就是这样吧,不清楚Socket,ConnectionInterceptor和CallServerInterceptor很难讲清楚 ,
ConnectionInterceptor 大概作用是:创建或者获取RealConnection,HttpCodec 和进行三次握手.
CallServerInterceptor :数据传输
ps:菜鸟一枚,不对望指正.