okhttp内置缓存策略,在CacheInterceptor中实现了缓存机制。okhttp3未做任何设置情况下,默认不使用缓存。okhttp缓存策略遵循了http协议缓存,因此了解okhttp缓存策略前需要有http缓存相关基础,可以参考《浏览器 HTTP 协议缓存机制详解》。
配置缓存
全局设置
如果需要使用okhttp的缓存机制,需要在构建OkHttpClient时给它设置Cache对象,例如:
// 参数1为缓存文件目录,参数2为缓存大小
Cache cache = new Cache(directory, maxSize);
new OkHttpClient.Builder().cache(cache).build();
看看Cache的构造函数,会发现它内部是封装了DiskLruCache来做缓存文件存取。
Cache(File directory, long maxSize, FileSystem fileSystem) {
this.cache = DiskLruCache.create(fileSystem, directory, VERSION, ENTRY_COUNT, maxSize);
}
单个请求配置缓存策略
若要为单个请求设置不同的缓存策略,可以给request设置CacheControl对象,它将会为请求加上Cache-Control请求头。
new Request.Builder().cacheControl(cacheControl).build();
public Builder cacheControl(CacheControl cacheControl) {
String value = cacheControl.toString();
if (value.isEmpty()) return removeHeader("Cache-Control");
return header("Cache-Control", value);
}
CacheControl对象可以通过Builder自行配置构建:
也可以使用CacheControl提供的两个配置:
/**
* Cache control request directives that require network validation of responses. Note that such
* requests may be assisted by the cache via conditional GET requests.
*/
public static final CacheControl FORCE_NETWORK = new Builder().noCache().build();
/**
* Cache control request directives that uses the cache only, even if the cached response is
* stale. If the response isn't available in the cache or requires server validation, the call
* will fail with a {@code 504 Unsatisfiable Request}.
*/
public static final CacheControl FORCE_CACHE = new Builder()
.onlyIfCached()
.maxStale(Integer.MAX_VALUE, TimeUnit.SECONDS)
.build();
- FORCE_NETWORK:强制使用网络请求,不使用缓存
- FORCE_CACHE:强制缓存,不进行网络请求
缓存拦截器机制
okhttp中的缓存策略有强制缓存和对比缓存:
- 强制缓存,即缓存在有效期内就直接返回缓存,不进行网络请求。
- 对比缓存,即缓存超过有效期,进行网络请求。若数据未修改,服务端返回不带body的304响应,表示客户端缓存仍有效可用;否则返回完整最新数据,客户端取网络请求的最新数据。
okhttp利过CacheStrategy对象中的networkRequest和cacheResponse来判断执行什么策略:
/** The request to send on the network, or null if this call doesn't use the network. */
public final @Nullable Request networkRequest;
/** The cached response to return or validate; or null if this call doesn't use a cache. */
public final @Nullable Response cacheResponse;
通过注释可以知道networkRequest是否为空决定是否请求网络,cacheResponse是否为空决定是否使用缓存
有4种组合情况(这里先了解对应结论,后面再分析生成规则):
1. networkRequest、cacheResponse均为空,构建返回一个状态码为504的response;
2. networkRequest为空、cacheResponse不为空,执行强制缓存
3. networkRequest、cacheResponse均不为空,执行对比缓存
4. networkRequest不为空、cacheResponse为空,网络请求获取到最新response后,视情况缓存response
缓存机制实现是在CacheInterceptor的intercept方法中,这里会根据前面配置的参数来执行相应策略: