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

whl*_*hlk 15 android okhttp retrofit2 okhttp3

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

客户定义:

Cache cache = new Cache(getCacheDirectory(context), 1024 * 1024 * 10);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .cache(cache)
            .build();
Run Code Online (Sandbox Code Playgroud)

Api定义:

@GET("/object")
Observable<Result<SomeObject>> getSomeObject();
Run Code Online (Sandbox Code Playgroud)

示例电话:

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); // ???
});
Run Code Online (Sandbox Code Playgroud)

Eri*_*ran 18

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

引用Jesse Wilson的话:

有几个组合.

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

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

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

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

boolean isFromCache(Result<?> result) {
  return result.response().raw().networkResponse() == null;
}
Run Code Online (Sandbox Code Playgroud)

  • 实际上最好检查`result.response().raw().cacheResponse() != null`。如果客户端重新验证缓存的响应并收到 304,则 `networkResponse()` 和 `cacheResponse()` 都将为非空。 (2认同)

seb*_*ian 7

解决方案1:

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

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

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

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

解决方案2:

您可以通过以下方式将Interceptor添加到OkHttp客户端new OkHttpClient.Builder().addInterceptor(...).在这个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;
});
Run Code Online (Sandbox Code Playgroud)

  • 它总是表明响应来自缓存!即使我卸载了应用程序! (2认同)
  • 解决方案 2 包含逻辑错误。根据 OkHttp 文档“cacheControl() 永远不会为空,即使此响应不包含 Cache-Control 标头” (2认同)