OkHttp3源码详解之HTTP重定向&缓存的处理(二)

接下来我们分析

  1. Cache是如何获取缓存的。
  2. 缓存策略是如何判断的。
Cache获取缓存

从Cache的get方法开始。它按以下步骤进行。

  1. 计算request对应的key值,md5加密请求url得到。
  2. 根据key值去DiskLruCache查找是否存在缓存内容。
  3. 存在缓存的话,创建缓存Entry实体。ENTRY_METADATA代表响应头信息,ENTRY_BODY代表响应体信息。
  4. 然后根据缓存Entry实体得到响应,其中包含了缓存的响应头和响应体信息。
  5. 匹配这个缓存响应和请求的信息是否匹配,不匹配的话要关闭资源,匹配的话返回。

public final class Cache implements Closeable, Flushable {
//获取缓存
Response get(Request request) {
//计算请求对应的key
String key = urlToKey(request);
DiskLruCache.Snapshot snapshot;
Entry entry;
try {
//这里从DiskLruCache中读取缓存信息
snapshot = cache.get(key);
if (snapshot == null) {
return null;
}
} catch (IOException e) {
// Give up because the cache cannot be read.
return null;
}

try {
//这里读取缓存的响应头信息
entry = new Entry(snapshot.getSource(ENTRY_METADATA));
} catch (IOException e) {
Util.closeQuietly(snapshot);
return null;
}
//然后得到响应信息,包含了缓存响应头和响应体信息
Response response = entry.response(snapshot);
//判断缓存响应和请求是否匹配,匹配url,method,和其他响应头信息
if (!entry.matches(request, response)) {
//不匹配的话,关闭响应体
Util.closeQuietly(response.body());
return null;
}

//返回缓存响应
return response;
}

//这里md5加密url得到key值
private static String urlToKey(Request request) {
return Util.md5Hex(request.url().toString());
}

}

如果存在缓存的话,在指定的缓存目录中,会有两个文件“.0”和“.1”,分别存储某个请求缓存的响应头和响应体信息。(“****”是url的md5加密值)对应的ENTRY_METADATA响应头和ENTRY_BODY响应体。缓存的读取其实是由DiskLruCache来读取的,DiskLruCache是支持Lru(最近最少访问)规则的用于磁盘存储的类,对应LruCache内存存储。它在存储的内容超过指定值之后,就会根据最近最少访问的规则,把最近最少访问的数据移除,以达到总大小不超过限制的目的。

接下来我们分析CacheStrategy缓存策略是怎么判定的。

CacheStrategy缓存策略

直接看CacheStrategy的get方法。缓存策略是由请求和缓存响应共同决定的。

  1. 如果缓存响应为空,则缓存策略为不使用缓存。
  2. 如果请求是https但是缓存响应没有握手信息,同上不使用缓存。
  3. 如果请求和缓存响应都是不可缓存的,同上不使用缓存。
  4. 如果请求是noCache,并且又包含If-Modified-Since或If-None-Match,同上不使用缓存。
  5. 然后计算请求有效时间是否符合响应的过期时间,如果响应在有效范围内,则缓存策略使用缓存。
  6. 否则创建一个新的有条件的请求,返回有条件的缓存策略。
  7. 如果判定的缓存策略的网络请求不为空,但是只使用缓存,则返回两者都为空的缓存策略。

public final class CacheStrategy {

public Factory(long nowMillis, Request request, Response cacheResponse) {
this.nowMillis = nowMillis;
//网络请求和缓存响应
this.request = request;
this.cacheResponse = cacheResponse;

if (cacheResponse != null) {
//找到缓存响应的响应头信息
Headers headers = cacheResponse.headers();
for (int i = 0, size = headers.size(); i < size; i++) {
//查看响应头信息中是否有以下字段信息
String fieldName = headers.name(i);
String value = headers.value(i);
if (“Date”.equalsIgnoreCase(fieldName)) {
servedDate = HttpDate.parse(value);
servedDateString = value;
} else if (“Expir

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值