OkHttp3缓存支持

1,868 阅读2分钟

需求背景

要求是每次网络请求之前都去取一遍缓存,如果有缓存则处理缓存数据刷新界面,继续走正常的网络请求,网络请求成功之后处理数据刷新界面,更新缓存,如果请求失败,给出提示类似于Toaste这种轻量级的提示;如果没有缓存,继续走正常的网络请求,网络请求成功之后处理数据刷新界面,更新缓存,如果请求失败,给出提示这个时候需要错误页面这种重量级的提示。这样的好处是对于某些实时性要求不高的接口,在网络情况或者接口不稳定的情况下,用户可以继续操作,提升用户体验。流程图如下:

流程图

配置

配置缓存

OkHttp3本身是支持缓存的,只是默认没有开启需要配置,如下

 okHttpClientBuilder.cache(new Cache(new File(XHttpManager.getInstance().getApplication().getCacheDir(), "OkHttpCache"),
                    XHttpManager.getInstance().getCacheSize()));

重点看下Cache这个类的构造方法如下:

 public Cache(File directory, long maxSize) {
    this(directory, maxSize, FileSystem.SYSTEM);
  }

第一个参数表示的是缓存路劲,推荐放到data/data/应用包名/cache目录下,这样的话用户清理缓存或者卸载应用的时候会一同被清理,也不需要特别处理文件外部写入以及读取的权限,第二个参数是缓存文件的总大小,超过这个大小会触发OkHttp的Lru机制进行处理,不宜过大也不宜过小。

配置拦截器

public class XCacheInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        okhttp3.Response originalResponse = chain.proceed(chain.request());
        String cacheControl = originalResponse.header("Cache-Control");
        Log.d("XCacheInterceptor", "cacheControl =" + cacheControl);
        if (cacheControl == null || cacheControl.contains("no-store") || cacheControl.contains("no-cache") ||
                cacheControl.contains("must-revalidate")) {
            return originalResponse.newBuilder()
                    .removeHeader("Pragma")
                    .header("Cache-Control", "public, max-age=0")
                    .build();
        }
        return originalResponse;

    }
}

可以看到我们只是对一些不支持缓存的接口的头信息进行修改以支持缓存。接下来我们把拦截器配置到OkhttpClient里面,如下:

okHttpClientBuilder.addNetworkInterceptor(new XCacheInterceptor());

注意这里要使用addNetworkInterceptor而不是addInterceptor因为我们只是对头信息进行修改,对请求的结果不需要特殊处理。 到这里其实关于OkHttp3的缓存就处理好了,另外需要在读取缓存的时候强制读取缓存,网络请求的时候强制获取网络数据避免数据紊乱

 XRequestBuilder builder = XRequestBuilder.create();
            if (isCache) {
                builder.cacheControl(CacheControl.FORCE_CACHE);
            } else {
                builder.cacheControl(CacheControl.FORCE_NETWORK);
            }