有没有办法检测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); // ???
});
答案 0 :(得分:16)
只要您有okhttp3.Response
(retrofit2.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