之前在使用网络请求缓存时,一直使用的是手动的方式。手动获取返回的数据,手动存储,手动读取缓存。这种方式麻烦、低效而且容易出错。在项目中一直使用的是retrofit2库作为网络库,retrofit2库本身并不支持存储,但是由于retrofit2基于okhttp实现,可以使用okhttp实现网络缓存。
首先我们要添加缓存地址和缓存最大体积
1 2 3
| File httpCacheDirectory = new File(getCacheDir(), "responses"); //设置缓存 10M Cache cache = new Cache(httpCacheDirectory, 10 * 1024 * 1024);
|
其次我们要创建okhttpclient,并且添加拦截器和缓存代码
1 2 3 4 5 6 7
| OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(interceptor) .cache(cache).build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .client(client) .build();
|
在这里最重要的就是拦截器的内容。一般情况下,我们设置缓存的目的无非两种,一是在请求时都直接读取已缓存的数据,二是在有网络时直接连接网络,没有网络时读取缓存数据,而这两者的区别都需要在拦截器中设置。
一、直接读取缓存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Interceptor interceptor = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Response response = chain.proceed(request); String cacheControl = request.cacheControl().toString(); if (TextUtils.isEmpty(cacheControl)) { cacheControl = "public, max-age=60"; //60秒之内读缓存 } return response.newBuilder() .header("Cache-Control", cacheControl) .removeHeader("Pragma") .build(); } };
|
其中读缓存的有效时间是60s,表示在60秒之内无论如何都会去取缓存。
二、有网时请求网络,无网络时读取缓存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| Interceptor interceptor = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Response response = chain.proceed(request); if(isNetworkAvailable()){ return response.newBuilder() .header("Cache-Control", "public, max-age=" + 0) .removeHeader("Pragma") .build(); }else{ int maxStale = 60 * 60 * 24 * 30; //缓存的最大时间是30天 return response.newBuilder() .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) .removeHeader("Pragma") .build(); } } };
|
在30天之内没网络的情况下会读取缓存。