OkHttp框架缓存的缺陷

前段时间在重构代码时,想直接将网络请求中的缓存替换成OkHttp自带的,结果却发现OkHttp的缓存系统在某些情况下是无效的。

问题

okhttp cache is useless without network

OkHttp缓存介绍

OkHttp的缓存类为Cache, 创建一个Cache对象后在OkHttpClient的内部Builder中进行设置即可:

1
2
3
4
// 创建Cache对象,设置缓存目录和缓存时间
Cache cache = new Cache(new File("cache_path"), 24*60*60);
// 设置缓存
OkHttpClient client = new OkHttpClient.Builder().cache(cache).build();

注意:上面的代码只是演示设置缓存的过程,在开发过程中一般会将client设计为单例模式,同时可能会进行更多设置。

缓存失效场景

现在的App为了全面分析用户的使用习惯,在网络请求时一般都会获取手机的一些硬件或网络信息,比如使用的网络环境。同时为了信息传输的安全性,可能还会对请求进行加密。在这些情况下OkHttp的缓存系统就会失效了,导致用户在无网络情况下不能访问缓存。

场景:网络请求中传递了随网络状态变化的参数。

Wi-Fi环境下网络请求的URL为:www.test.com/?id=1&name=”Hello”&network=”Wifi”

在有网络的时候, 访问是正常的,并且对数据进行了缓存,但是当没有网络时,OkHttp会请求缓存数据,而缓存的存储规则就是Key-Value,使用URL的Md5字符串进行匹配时,因为URL发生了变化(此时的URL可能为www.test.com/?id=1&name=”Hello”&network=),导致不能匹配到相应的内容,缓存访问失败。

解决方案

  1. 先过滤可变参数,然后进行手动缓存,;
  2. 不要使用随网络状态变化的参数;

总结

其实现在的网络缓存系统基本都是采用以URL的Md5字符串为Key, 访问内容为Value的存储方式。在访问缓存时通过URL的Md5方式进行匹配,从而获取缓存的内容。所以在使用缓存系统时,需要对URL进行过滤,过滤掉随网络状态改变的参数再进行缓存,否则将无法匹配到缓存的内容。

,