缓存机制
缓存的优点:
- 减少访问服务器的次数,降低服务器的负荷
- 当没有网络的时候,界面不会显示空白,提高用户体验
缓存机制的原理:
我们请求服务器,然后由服务器返回的响应(Response) 中添加的头信息中有 Cache-control 字段,它的目的是告诉客户端是要从本地读取缓存还是直接从服务器获取消息。它有不同的值,每一个值有不同的作用。
如果我们需要满足这样的一个需求:“没有网络时读取本地缓存,有网络时获取服务器最新数据”就得做出判断:
- 没有网络时将Cache-control 的字段值替换为“public, only-if-cached, max-stale=" + 4 * 24 * 60 * 60"”,意思是无网络时,设置离线缓存时间为4周,超过4周后不再读取缓存,重新访问服务器。
- 有网络时将Cache-control 的字段值替换为“" public, max-age=" + 60”,意思是有网络时,设置在线缓存时间为60秒,在线缓存60秒内能读取,之后重新访问服务器获取最新数据。
因此,需要Interceptor(拦截器)得到response的heade信息,从而进行以上配置。
-
自定义Interceptor
Interceptor的概念不再赘述,请参考http://www.jianshu.com/p/2710ed1e6b48:
Interceptor mInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
//当没有网络时
if (!isConnectingToInternet()) {
request = request.newBuilder()
//CacheControl.FORCE_CACHE; //仅仅使用缓存
//CacheControl.FORCE_NETWORK;// 仅仅使用网络
.cacheControl(CacheControl.FORCE_CACHE)
.build();
}
Response proceed = chain.proceed(request);
if (isConnectingToInternet()) {
//有网络时
return proceed.newBuilder()
//清除头信息
.removeHeader("Pragma")
//设置在线缓存时间为60秒,
.header("Cache-Control", "public, max-age=" + 60)
.build();
} else {
//没网络时
int maxTime = 4 * 24 * 60 * 60;//离线缓存时间:4周
return proceed.newBuilder()
.removeHeader("Pragma")
//设置离线缓存时间为4周,
.header("Cache-Control", "public, only-if-cached, max-stale=" + maxTime)
.build();
}
}
};
总缓存时间=在线缓存时间+设置离线时的缓存时间(max-stale和max-age的和)
max-stale的值:指的是缓存的过期时间,设置它后,会将数据缓存,如果超过了过期时间,那么我们认为数据过期了,会重新从获取网络数据进行更新,但是,它是不会删除缓存的。
max-age的值:指的是缓存的生存时间,超过了就会删除该请求的缓存。
- 缓存文件
File file = new File(getCacheDir(), "whstywh");//缓存文件路径
Cache cache = new Cache(file, 10 * 1024 * 1024);//缓存文件大小为10MB
缓存文件全是以url的md5加密字段为文件名,每一个response分两个文件保存,以.0和.1结尾的文件区分。 进去看里面的内容如下:
.0的文件记录header的信息:
.1文件里面是返回的具体内容,即json数据。由此可见,这里的缓存机制也是一开始先把json缓存进文件,没有网络的时候再读取json进行解析。
journal.文件里面保存的是每一条reponse记录状态。包括读取,删除,写入等动作。
实现
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(mInterceptor)//添加应用拦截器
.addNetworkInterceptor(mInterceptor)//添加网络拦截器
.cache(cache)//设置缓存
.connectTimeout(5, TimeUnit.SECONDS)//连接超时 5秒
.build();
Retrofit retrofit = new Retrofit.Builder()
.client(client)
.baseUrl("http://www.yuyigufen.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
...
- OkHttp 3 只能缓存Get请求,post请求是不会进行缓存,主要是因为get请求的数据一般是比较持久的,而post一般是交互操作,缓存意义不大。
对于retrofit的学习才刚刚开始!
retrofit :入门
retrofit :Json数据缓存
retrofit :文件断点下载