本来是应该分析 CacheInterceptor 缓存拦截器的,考虑到这需要对OkHttp的缓存 Cache 有一定的了解,所以先分析 Cache 之后再对 CacheInterceptor 缓存拦截器进行分析。
Cache缓存我的理解就是节省客服端下一次请求网络的时间,更快的展示数据。
我们先看下是怎么样使用这个功能的:
OkHttpClient client = new OkHttpClient.Builder()
.cache(new Cache(new File("cache"),24*1024*1024))
.build();
调用了 OkHttpClient 的内部类 Builder 的 cache() 方法,并传入了一个 Cache 对象。 可以明白如果要使用缓存,只需要在创建 OkHttpClient 对象时配置 Cache 类就行了。
接下来看下实例化 Cache 的构造方法传入参数:
通过这个构造方法就可以设置好缓存路劲和大小。
接下来我们继续到 Cache 类的源码中去查看:
在 Cache 的源码上部分看到创建好了一个 InternalCache 对象,那这个 InternalCache 是个什么对象呢,点击过去:
发现其实就是一个接口,在这接口中很多的方法(get,put,remove,update等等)。
这也就明白了这个 InternalCache 接口的所有方法实现都是通过 Cache 类来进行实现的。
Cache的put方法
这是 put 方法的前面部分,继续看后面部分
后面部分东西还是挺多的,所以就以这种标号的方式进行分析,如下:
1:Entry 就是需要写入缓存的内容。
到源码中去查看:
可以看到 Entry 是一个 final 类,里面包含了请求的一些参数(url,请求头,请求方式,响应头等等),这个 Entry 类其实就是OkHttp把缓存中所需要的属性进行了封装,成了一个包装类,以便于我们进行缓存。
2:DiskLruCache(缓存算法)——从而也就知道了OkHttp中的缓存是通过DiskLruCache实现的。
Editor(DiskLruCache.Editor) 是DiskLruCache的内部类,主要是用于写入的。
3:cache其实就是一个DiskLruCache对象
4:key(...)方法,到这个方法的源码
可以清楚这个key()方法就是将请求的URL通过MD5的加密,然后得到加密后的十六进制的值。然后这个值也就是接下来缓存的key值。
5:cache.edit(...) 就是调用了DiskLruCache的edit()然后返回了Editor(DiskLruCache.Editor)对象
6:entry.writeTo(...) 刚刚知道entry就是缓存需要写入的部分,然后调用writeTo()这个方法。可以看看这个方法
可以知道在这个writeTo()方法中,就是把请求缓存写入磁盘。不仅仅缓存了响应的头部信息还缓存了请求的头部信息。
在 "6" 中我们发下已近对请求的头部响应的头部都进了缓存,那关键的响应体Response的缓存呢?就是接下来的 "7" 了。
7:源码是 return new CacheRequestImpl(editor);
知道这个put是返回了一个CacheRequest接口对象
在CacheRequestImpl类中实现了这个CacheRequest接口
那CacheRequestImpl类中为什么要去实现了这个CacheRequest接口呢,这就和 CacheInterceptor 缓存拦截器有关联了。主要是通过这个CacheRequest接口暴露给CacheInterceptor 缓存拦截器的,然后缓存拦截器就可以直接通过CacheRequestImpl实现类来更新和写入缓存数据。
到这个这个Cache的put方法都分析完了
put方法总结
1:首先判断请求的请求方式是否符合缓存要求GET
2:创建以一个Entry对象,包装了用于缓存所需要的信息(url,头部等等)
3:使用到DiskLruCache来进行缓存的实际写入
4:返回了一个CacheRequestImpl对象,这个对象主要是用于CacheInterceptor缓存拦截器的