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