需求
- 有网络的情况下总是去访问服务器获取最新的数据,并把数据缓存到本地
- 无网络的情况下直接去缓存里找数据,如果没有找到就抛出异常 (提示:当前没有网络连接)
- 部分配置缓存的接口启用缓存
实现
- 主要就是用到了okhttp的拦截器,通过修改请求头的Cache-Control来实现缓存
- 关于okhttp的拦截器我们用到了两个方法addInterceptor和addNetworkInterceptor
addInterceptor和addNetworkInterceptor
addInterceptor优先addNetworkInterceptor执行 有网络的情况下addInterceptor和addNetworkInterceptor都会执行 没有网络的情况下addInterceptor执行,而addNetworkInterceptor不会执行 没有网络但是有缓存的情况下addInterceptor会执行,而addNetworkInterceptor不会执行
代码实现
public class CacheInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();// 拦截请求头 判断哪些接口配置上了缓存(该配置是在retrofit上配置)String cacheControl = request.cacheControl().toString();// 如果没有配置过 那么就是走正常的访问,这里直接return回去了,并没有对请求做处理if(TextUtils.isEmpty(cacheControl)) {return chain.proceed(builder.build());}// 如果没有网络的情况下,并且配置了缓存,那么我们就设置强制读取缓存,没有读到就抛异常 503,但是并不会去服务器请求数据if (!NetworkUtils.isConnected()) {// 缓存一周int offlineCacheTime = 60 * 60 * 24 * 7;request = request.newBuilder()// only-if-cached 强制使用缓存// max-stale 即使这个缓存已经过期了,只要在max-stale这个时间内,还可以使用过期的缓存.header("Cache-Control", "public, only-if-cached, max-stale=" + offlineCacheTime).build();}return chain.proceed(request);}}
// 跟平时retorfit写法一样,只是添加了@Headers这个配置@Headers("Cache-Control:public, max-age=0")@GET("user/account/getStudent/v1.0")Observable<BaseResBean<UserBean>> getUserInfo(@QueryMap HashMap<String, Object> map);
public OkHttpClient provideOkHttpClient(Context context) {// 先进行缓存目录的配置File httpCacheDirectory = new File(context.getCacheDir(), "OkHttpCache");// 设置缓存文件大小为10Mint cacheSize = 10 * 1024 * 1024;Cache cache = new Cache(httpCacheDirectory, cacheSize);OkHttpClient.Builder builder = new OkHttpClient.Builder()...// 缓存配置.cache(cache)// 启用缓存拦截器.addInterceptor(new CacheInterceptor());return builder.build();}
