Модернизация ETAG и кеширование
Есть ли правильное объяснение того, как добавить кеширование и ETAG
/If-None-Match
поддержка дооснащения +OkHttp? Я изо всех сил пытаюсь добавить Etag
поддержка двух проектов, и сначала я подозревал, что может быть проблема с заголовками HTTP, в другом проекте все настроено правильно, и кэширование все еще не работает должным образом.
Ниже приведены мои попытки заставить его работать. Результаты показывают, что кеширование работает в одном и том же экземпляре приложения, но как только я перезагружаюсь, все снова загружается долго. Кроме того, в моих журналах я не видел If-None-Match
добавляется в запрос, поэтому я предполагаю, что сервер не знает о ETag
и до сих пор полностью пересчитывает ответ.
Вот несколько примеров кода:
public class RetrofitHttpClient extends UrlConnectionClient
{
private OkUrlFactory generateDefaultOkUrlFactory()
{
OkHttpClient client = new com.squareup.okhttp.OkHttpClient();
try
{
Cache responseCache = new Cache(baseContext.getCacheDir(), SIZE_OF_CACHE);
client.setCache(responseCache);
}
catch (Exception e)
{
Logger.log(this, e, "Unable to set http cache");
}
client.setConnectTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS);
client.setReadTimeout(CONNECT_TIMEOUT, TimeUnit.MILLISECONDS);
return new OkUrlFactory(client);
}
private final OkUrlFactory factory;
public RetrofitHttpClient()
{
factory = generateDefaultOkUrlFactory();
}
@Override
protected HttpURLConnection openConnection(retrofit.client.Request request) throws IOException
{
return factory.open(new URL(request.getUrl()));
}
}
Затем создается оставшийся адаптер с уровнем журнала FULL и пользовательским тегом:
restAdapter = new RestAdapter.Builder()
.setClient(new RetrofitHttpClient())
.setEndpoint(Config.BASE_URL)
.setRequestInterceptor(new SignatureSetter())
.setConverter(new JacksonConverter(JsonHelper.getObjectMapper()))
.setLogLevel(RestAdapter.LogLevel.FULL)
.setLog(new AndroidLog("=NETWORK="))
.build();
У меня длинный запрос на первом экране приложения для тестирования. Когда я открываю приложение - для завершения запроса требуется 7 секунд. Если я приостанавливаю и возобновляю приложение - тот же запрос занимает 250 мс, явно попав в кеш. Если я полностью закрою приложение и перезапущу - это снова займет 7 секунд.
ОБНОВЛЕНИЕ: Как было предложено, я использовал пользовательскую сборку Retrofit и подключил LoggingInterceptor. Вот что я получаю.
Received response for *** in 449,3ms
Date: Wed, 07 Jan 2015 09:02:23 GMT
Server: Apache
X-Powered-By: PHP/5.4.31
Access-Control-Allow-Credentials: true
Pragma:
Cache-Control: public, max-age=3600
X-Frame-Options: SAMEORIGIN
Etag: "hLxLRYztkinJAB453nRV7ncBSuU=-gzip"
Last-Modified: Wed, 24 Dec 2014 13:09:04 GMT
Vary: Accept-Encoding
Content-Encoding: gzip
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
OkHttp-Selected-Protocol: http/1.1
OkHttp-Sent-Millis: 1420621288104
OkHttp-Received-Millis: 1420621288554
Sending request **** on Connection{****:80, proxy=DIRECT@ hostAddress=**** cipherSuite=none protocol=http/1.1}
Accept: application/json;
Host: ****
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/2.2.0
Response is equal to described above
Как видите, нет If-None-Match
заголовок присутствует в следующем запросе.
3 ответа
Я вижу, что этот вопрос продолжает привлекать внимание, и как только я не смогу найти реальный ответ - я сейчас провожу исследование по этой теме и закрываю ветку.
Конечным результатом исследования и некоторых обсуждений в модификациях и потоках okhttp на GitHub было то, что в OkHttp предположительно существовала проблема, которая могла помешать установке тега If-None-Match для исходящих запросов.
Предполагалось, что проблема будет исправлена в OkHttp 2.3, и я использую здесь "предполагается", потому что я еще не проверял, действительно ли это работает. Тестирование было трудным, потому что я использовал Retrofit, и само Retrofit пришлось обновить, чтобы использовать новую версию OkHttp и добавить некоторую новую поддержку Interceptors, чтобы иметь возможность отлаживать все заголовки, которые установлены OkHttp. Связанная нить здесь: https://github.com/square/okhttp/issues/831
Я не уверен, что Retrofit был обновлен после этого. Надеюсь, что так и было, поэтому есть большая вероятность, что проблема уже исправлена, и Etag должен работать правильно - просто убедитесь, что у вас установлены последние версии Retrofit и OkHttp.
Я постараюсь проверить все сам, как только у меня будет время.
Использование перехватчиков OkHttp поможет вам диагностировать заголовки, входящие и выходящие из вашего приложения. Документ перехватчиков дает пример кода перехватчика, который регистрирует заголовки запросов и ответов в сети. Вы можете использовать это как есть.
class LoggingInterceptor implements Interceptor {
@Override public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
long t1 = System.nanoTime();
logger.info(String.format("Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers()));
Response response = chain.proceed(request);
long t2 = System.nanoTime();
logger.info(String.format("Received response for %s in %.1fms%n%s",
response.request().url(), (t2 - t1) / 1e6d, response.headers()));
return response;
}
}
Чтобы подключить его к Retrofit, вам нужно получить предварительный снимок Retrofit. По состоянию на январь 2015 года версии Retrofit, поставляемые в настоящее время, не участвуют в перехватчиках OkHttp. Скоро выйдет релиз, но он еще не готов.
У меня была похожая проблема: OkHttp никогда не работал с кешем, даже когда сервер отправлял тот же ETAG.
Моя проблема была SIZE_OF_CACHE
, Я определял очень маленький размер.
Попробуйте увеличить его (у меня работает что-то вроде 10 * 1024 * 1024) Также вы можете исследовать / data / data // files / cache, чтобы увидеть, действительно ли там что-то хранится