Detect if OkHttp response comes from cache (with Retrofit)

whlk picture whlk · Jan 18, 2017 · Viewed 7k times · Source

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); // ???
});

Answer

Eric Cochran picture Eric Cochran · Jan 18, 2017

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;
}