2.4 Okhttp缓存的启用
要开启使用Okhttp的缓存其实很简单,只需要给OkHttpClient对象设置一个Cache对象即可,创建一个Cache时指定缓存保存的目录和缓存最大的大小即可。
//新建一个cache,指定目录为外部目录下的okhttp_cache目录,大小为100M
Cache cache = new Cache(new File(Environment.getExternalStorageDirectory() + “/okhttp_cache/”), 100 * 1024 * 1024);
将cache设置到OkHttpClient中,这样缓存就开始生效了。
OkHttpClient client = new OkHttpClient.Builder().cache(cache).build();
那么下面我们来看看Okhttp缓存执行的大概流程
2.5 Okhttp的缓存流程
Okhttp的缓存流程分为读取缓存和存储缓存两个过程,我们分别分析。
Okhttp读取缓存流程
读取使用缓存的流程从HttpEngine的sendRequest发送请求开始。
- 首先获取OkHttpClient的Cache缓存对象,就是之前创建OkHttpClient时设置的Cache。
- 然后传入Request请求到Cache的get方法去查找缓存响应数据Response。
- 构造一个缓存策略,传入Request请求和缓存响应Response,然后调用它的get方法去决策使用网络请求还是缓存响应。
- 策略判定之后,如果是使用缓存,则它的cacheResponse不为空,networkRequest为空,如果使用请求,则相反。然后再将策略给出的这两个值,继续处理。
- 如果使用请求,但是之前又找到了缓存响应,则要关闭缓存响应资源。
- 如果策略得出缓存响应为空,网络请求也为空,则返回请求不合理的响应。(比如强制使用缓存,但是找不到缓存的情况下)
- 如果请求为空,缓存不为空,也就是使用缓存的情况,则使用缓存响应来构造返回的响应数据。
- 最后就是只使用网络请求的情况,走网络请求路线。
总的来说就是,先查找是否有可用的Cache,然后通过Cache找到请求对应的缓存,然后将请求和缓存交给缓存策略去判断使用请求还是缓存,得出结果后,自己再判断使用缓存还是请求,如果使用缓存,用缓存构造响应直接返回,如果使用请求,那么开始网络请求流程。
public final class HttpEngine {
//发送请求
public void sendRequest() throws RequestException, RouteException, IOException {
if (cacheStrategy != null) return; // Already sent.
if (httpStream != null) throw new IllegalStateException();
//根据用户请求得到实际的网络请求
Request request = networkRequest(userRequest);
//这里InternalCache就是对Cache的封装,它的实现在Cache的internalCache中。
InternalCache responseCache = Internal.instance.internalCache(client);
//通过Cache的get方法查找缓存响应
Response cacheCandidate = responseCache != null
? responseCache.get(request)
: null;
long now = System.currentTimeMillis();
//构造缓存策略,然后进行策略判断
cacheStrategy = new CacheStrategy.Factory(now, request, cacheCandidate).get();
//策略判定后的网络请求和缓存响应
networkRequest = cacheStrategy.networkRequest;
cacheResponse = cacheStrategy.cacheResponse;
if (responseCache != null) {
//使用缓存响应的话,记录一下使用记录
responseCache.trackResponse(cacheStrategy);
}
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) {
//强制使用缓存,又找不到缓存,就报不合理请求响应了
userResponse = new Response.Builder()
.request(userRequest)
.priorResponse(stripBody(priorResponse))
.protocol(Protocol.HTTP_1_1)
.code(504)
.message(“Unsatisfiable Request (only-if-cached)”)
.body(EMPTY_BODY)
.build();
return;
}
//上面情况处理之后,就是使用缓存返回,还是网络请求的情况了
// If we don’t need the network, we’re done.
if (networkRequest == null) {
//使用缓存返回响应
userResponse = cacheResponse.newBuilder()
.request(userRequest)
.priorResponse(stripBody(priorResponse))
.cacheResponse(stripBody(cacheResponse))
.build();
userResponse = unzip(userResponse);
return;
}
//使用网络请求
//下面就是网络请求流程了,略
…
}
}
接下来我们分析
- Cache是如何获取缓存的。
- 缓存策略是如何判断的。