繁体   English   中英

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

[英]Detect if OkHttp response comes from cache (with Retrofit)

有没有办法检测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); // ???
});

只要有okhttp3.Responseokhttp3.Responseretrofit2.Response.raw() ),就可以检查响应是否来自缓存。

引用Jesse Wilson的话:

有几个组合。

仅限 .networkResponse() - 您的请求来自网络。

.cacheResponse() 唯一的 -你的请求是从缓存中提供完全。

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

因此,对于您的示例, isFromCache方法如下所示:

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

解决方案1:

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

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

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

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

解决方案2:

您可以通过new OkHttpClient.Builder().addInterceptor(...)将一个Interceptor添加到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;
});
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,你在流中传递的响应来自网络而不是缓存(取决于你在CacheControl上指定的maxStale) 。 因此,检查networkResponse是否为null,如果为null且cacheResponse不为null,则响应从缓存提供,反之亦然。

太晚了但也许这对某人有帮助。 当内容来自网络时: response.networkResponse()response.cacheResponse()不为null,当内容来自缓存response.networkResponse()为null时,来自@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;
    }
});

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM