检测OkHttp响应是否来自缓存(使用Retrofit)

时间:2017-01-18 19:22:30

标签: android retrofit2 okhttp okhttp3

有没有办法检测Retrofit响应是来自配置的OkHttp缓存还是实时响应?

客户定义:

Cache cache = new Cache(getCacheDirectory(context), 1024 * 1024 * 10);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .cache(cache)
            .build();

Api定义:

@GET("/object")
Observable<Result<SomeObject>> getSomeObject();

示例电话:

RetroApi retroApi = new Retrofit.Builder()
            .client(okHttpClient)
            .baseUrl(baseUrl)
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(RetroApi.class);

result = retroApi.getSomeObject().subscribe((Result<SomeObject> someObjectResult) -> {
     isFromCache(someObjectResult); // ???
});

5 个答案:

答案 0 :(得分:16)

只要您有okhttp3.Responseretrofit2.Response.raw()),就可以检查回复是否来自缓存。

引用Jesse Wilson的话:

  

有几个组合。

     

.networkResponse() - 您的请求仅通过网络提供。

     

.cacheResponse() - 您的请求是专门从缓存中提供的。

     

.networkResponse()和.cacheResponse() - 您的请求是条件GET,因此标头来自网络,而正文来自缓存。

因此,对于您的示例,isFromCache方法看起来像:

boolean isFromCache(Result<?> result) {
  return result.response().raw().networkResponse() == null;
}

答案 1 :(得分:7)

解决方案1:

通过使用okhttp3.Response.cacheResponse(),您可以检查是否从缓存中收到了响应:

  

返回从缓存接收的原始响应。如果此响应未使用缓存

,则为null

要从您的改装响应中获取原始OkHttp响应,请使用.raw()。即:

public boolean isFromCache(Result<?> retroResult) {
    return retroResult.response().raw().cacheResponse() != null;
}

解决方案2:

您可以通过new OkHttpClient.Builder().addInterceptor(...)将拦截器添加到OkHttp客户端。 在此Interceptor中,通过chain.proceed(chain.request)检索响应。 然后分别使用Response.cacheResponse() Response.networkResponse()来确定响应的来源。

完整代码:

new OkHttpClient.Builder().addInterceptor(chain -> {
        Response response = chain.proceed(chain.request());
        if (response.cacheControl() != null) {
            // from cache
        } else if (response.networkResponse() != null) {
            // from network
        }
        return response;
});

答案 2 :(得分:1)

if (response.raw().cacheResponse() != null) {  
    // true: response was served from cache
}

if (response.raw().networkResponse() != null) {  
    // true: response was served from network/server
}

但是我建议你检查你的networkResponse是否为空,因为一旦请求被缓存并且你有一个networkResponse,你传递的流的响应来自网络而不是缓存(取决于你可能指定的maxStale)在CacheControl上)。因此,检查networkResponse是否为null,如果为null且cacheResponse不为null,则响应从缓存提供,反之亦然。

答案 3 :(得分:0)

为时已晚,但这也许会对某人有所帮助。当内容来自网络时:response.networkResponse()response.cacheResponse()不为空,当内容来自缓存时response.networkResponse()为空,因此来自@sebastian的代码:

new OkHttpClient.Builder().addInterceptor(chain -> {
        Response response = chain.proceed(chain.request());
        if (response.cacheControl() != null) {
            // from cache
        } else if (response.networkResponse() != null) {
            // from network
        }
        return response;
});

只需替换为以下代码:

OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
okHttpClientBuilder.addInterceptor(new Interceptor() {
    @NonNull
    @Override
    public Response intercept(@NonNull Chain chain) throws IOException {
        Response response = chain.proceed(chain.request());
        if (response.networkResponse() != null) {
            Log.v(TAG, "Response from networkResponse(): " + response.networkResponse());
        } else if (response.cacheResponse() != null) {
            Log.v(TAG, "Response from cacheControl(): " + response.cacheResponse());
        }
        return response;
    }
});

答案 4 :(得分:0)

如果cacheResponse存在,则响应来自缓存 AND networkResponse(如果存在)的响应代码为304。请参阅:https://github.com/square/okhttp/issues/4539