Обнаружение ответа OkHttp из кеша (с помощью 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); // ???
});
Ответы
Ответ 1
В любое время, когда вы okhttp3.Response
(retrofit2.Response.raw()
), вы можете проверить, является ли ответ кешем.
Процитировать Джесси Уилсон:
Есть несколько комбо.
. networkResponse() только - ваш запрос был подан только из сети.
. cacheResponse() только - ваш запрос был отправлен исключительно из кеша.
.networkResponse() и .cacheResponse() - ваш запрос был условным GET, поэтому заголовки из сети и тела из кеша.
Итак, для вашего примера метод isFromCache
будет выглядеть так:
boolean isFromCache(Result<?> result) {
return result.response().raw().networkResponse() == null;
}
Ответ 2
Решение 1:
Используя okhttp3.Response.cacheResponse(), вы можете проверить, был ли получен ответ от кеша:
Возвращает необработанный ответ, полученный из кеша. Будет null, если этот ответ не использовал кеш
Чтобы получить необработанный ответ OkHttp от вашего адаптационного ответа, используйте .raw()
. то есть:.
public boolean isFromCache(Result<?> retroResult) {
return retroResult.response().raw().cacheResponse() != null;
}
Решение 2:
Вы можете добавить Interceptor к клиенту OkHttp через new OkHttpClient.Builder().addInterceptor(...)
.
В этом перехватчике получить ответ через 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;
});
Ответ 3
if (response.raw().cacheResponse() != null) {
// true: response was served from cache
}
if (response.raw().networkResponse() != null) {
// true: response was served from network/server
}
Но я бы посоветовал вам проверить, является ли ваш networkResponse нулевым, поскольку после того, как запрос будет кэширован, и у вас есть сетевой ответ, ваш ответ передается потоком из сети, а не в кеш (в зависимости от maxStale, который вы, возможно, указали на CacheControl). Поэтому проверьте, не является ли networkResponse нулевым, если null и ваш cacheResponse не являются нулевыми, ответ будет отправлен из кэша иначе наоборот.
Ответ 4
Слишком поздно, но, возможно, это будет полезно для кого-то. Когда контент поступает из сети: 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;
}
});
Ответ 5
Ответ приходит из кэша, если cacheResponse существует и networkResponse (если существует) имеет код ответа 304. См: https://github.com/square/okhttp/issues/4539