[英]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.Response
( okhttp3.Response
( retrofit2.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.