问题
Is there a way to detect if a Retrofit response comes from the configured OkHttp cache or is a live response?
Client definition:
Cache cache = new Cache(getCacheDirectory(context), 1024 * 1024 * 10);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.cache(cache)
.build();
Api definition:
@GET("/object")
Observable<Result<SomeObject>> getSomeObject();
Example call:
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); // ???
});
回答1:
Any time you have an okhttp3.Response (retrofit2.Response.raw()
), you can check if the response is from the cache.
To quote Jesse Wilson:
There are a few combos.
.networkResponse() only – your request was served from network exclusively.
.cacheResponse() only – your request was served from cache exclusively.
.networkResponse() and .cacheResponse() – your request was a conditional GET, so headers are from the network and body is from the cache.
So for your example, the isFromCache
method would look like:
boolean isFromCache(Result<?> result) {
return result.response().raw().networkResponse() == null;
}
回答2:
Solution 1:
By using the okhttp3.Response.cacheResponse() you can check if the response was received from the cache:
Returns the raw response received from the cache. Will be null if this response didn't use the cache
To get the raw OkHttp response from your retrofit Response obect use .raw()
. i.e.:
public boolean isFromCache(Result<?> retroResult) {
return retroResult.response().raw().cacheResponse() != null;
}
Solution 2:
You can add an Interceptor to the OkHttp Client via new OkHttpClient.Builder().addInterceptor(...)
.
In this Interceptor retrieve the response via chain.proceed(chain.request)
.
Then use Response.cacheResponse()
respectively Response.networkResponse()
to determine where the response came from.
Full code:
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;
});
回答3:
if (response.raw().cacheResponse() != null) {
// true: response was served from cache
}
if (response.raw().networkResponse() != null) {
// true: response was served from network/server
}
But I would suggest you to check if your networkResponse is null, since once the request is cached and you have a networkResponse too, your response passed down the stream is from network and not cache(Depending on the maxStale you might have specified on CacheControl). So check if networkResponse is not null, if null and your cacheResponse is not null, the response is served from cache else vice versa.
回答4:
Too late but maybe this would be helpful for someone. When content comes from network: response.networkResponse()
and response.cacheResponse()
are not null, when content comes from cache response.networkResponse()
is null, so code from @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;
});
just replace with this code:
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;
}
});
回答5:
The response comes from cache if cacheResponse exists AND networkResponse (if exists) has a response code of 304. See: https://github.com/square/okhttp/issues/4539
来源:https://stackoverflow.com/questions/41727750/detect-if-okhttp-response-comes-from-cache-with-retrofit