在okhttp3中超时时提供缓存

时间:2018-09-26 15:10:00

标签: android okhttp3

在okhttp3中,如果我的连接在CONNECT或READ中超时,是否可以通过某种方式从okhttp获取缓存?除了连接失败之外,我还想从离线缓存中为用户提供服务,以防请求花费太长时间。

1 个答案:

答案 0 :(得分:0)

我确实遇到过类似的问题。每当请求超时(我不介意处于哪种状态),连接中断或无可用连接时,我都希望回退到缓存。为此,我制作了一个拦截器,该拦截器将首先检查连接性,然后在发出请求时也捕获异常。如果超时,则会引发异常,然后我们退回到主动缓存。

因此,基本上,您首先需要设置okhttp客户端以使用缓存,然后使用拦截器以更好的方式使用该缓存。

public OkHttpClient getOkHttpClient() {
    File cacheFile = new File(context.getCacheDir(), "okHttpCache");
    Cache cache = new Cache(cacheFile, CACHE_SIZE);

    ConnectivityInterceptor connectivityInterceptor = new ConnectivityInterceptor(networkStateHelper);
    OkHttpClient.Builder builder = new OkHttpClient.Builder().cache(cache).addInterceptor(connectivityInterceptor);
    return builder.build();
}

之后,您可以使用此简单的拦截器来强制使用缓存。通常,当服务器响应340时会使用缓存,这意味着没有更改,因此我们可以获取缓存的响应,但这当然需要有效的Internet连接。但是,我们可以强制使用缓存,因此如果可能的话,它将直接从缓存中获取任何响应,这在您离线或超时时会派上用场

public class ConnectivityInterceptor implements Interceptor {

    // NetworkStateHelper is some class we have that checks if we are online or not.
    private final NetworkStateHelper networkStateHelper;

    public ConnectivityInterceptor(NetworkStateHelper networkStateHelper) {
        this.networkStateHelper = networkStateHelper;
    }

    @Override
    public Response intercept(@NonNull Chain chain) throws IOException {
        // You can omit this online check or use your own helper class
        if (networkStateHelper.isNotOnline()) {
            return getResponseFromCache(chain, request);
        }
        try {
            Response response = chain.proceed(request);
            return new Pair<>(request, response);
        }
        catch (Exception exception) {
            Log.w(exception, "Network failure discovered, trying cache fallback");
            return getResponseFromCache(chain, request);
        }

    }

    private Response getResponseFromCache(Interceptor.Chain chain,
            Request request) throws IOException {
        // We just create a new request out of the old one and set cache headers to it with the cache control. 
        // The CacheControl.FORCE_CACHE is already provided by OkHttp3
        request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build();

        // Now we proceed with the request and OkHttp should automatically fetch the response from cache or return
        // a failure if it is not there, some 5xx status code
        return chain.proceed(request);
    }

}