Intereting Posts
Java.lang.NoClassDefFoundError: android.support.v7.app.AppCompatDelegateImplV14 в Android Studio Приложение рушится на спине, нажатой при использовании карты внутри фрагмента в андроиде? Как создать ссылки на ссылку для классов Android в javadoc? Электронная почта с внутреннего хранилища Можно ли отключить прокрутку на ViewPager Реагирование на многоканальные проводные наушники Насколько хорошо поддерживается чувствительность к давлению на устройствах Android? Android.widget.SeekBar не может быть добавлен в файл android.widget.TextView Проводник файлов всегда пуст в Eclipse Тестирование Android-модуля с использованием проекта ant с библиотекой Как показать ту же часть игры на каждом соотношении сторон на устройствах Android с Unity? Разница между onSingleTapConfirmed и onSingleTapUp Аварийный переход от общего элемента для устройств Lollipop Запретить пользователям одновременно нажимать две кнопки? Поиск по поиску в Интернете не работает

Правильный способ настройки кеша для OkHttp в Android

Я пытаюсь настроить кеш для OkHttp, поэтому он только запрашивает сервер в первый раз, когда я пытаюсь получить ответ с сервера до истечения срока годности заголовка или заголовок управления кешем, который поступает с сервера, делает недействительным ответ Из кеша.

В настоящее время он кэширует ответ, но не использует его при повторном запросе ресурса. Возможно, это не так, как предполагалось.

Я настраиваю OkHttpClient с кешем следующим образом:

public static Cache createHttpClientCache(Context context) { try { File cacheDir = context.getDir("service_api_cache", Context.MODE_PRIVATE); return new Cache(cacheDir, HTTP_CACHE_SIZE); } catch (IOException e) { Log.e(TAG, "Couldn't create http cache because of IO problem.", e); return null; } } 

Это используется следующим образом:

 if(cache == null) { cache = createHttpClientCache(context); } sClient.setCache(cache); 

Вот как я делаю один из запросов на сервер с OkHttp, который фактически не использует кеш:

 public static JSONObject getApi(Context context) throws IOException, JSONException, InvalidCookie { HttpCookie sessionCookie = getServerSession(context); if(sessionCookie == null){ throw new InvalidCookie(); } String cookieStr = sessionCookie.getName()+"="+sessionCookie.getValue(); Request request = new Request.Builder() .url(sServiceRootUrl + "/api/"+API_VERSION) .header("Accept", "application/json") .header("Cookie", cookieStr) .build(); Response response = sClient.newCall(request).execute(); if(response.code() == 200){ String charset = getResponseCharset(response); if(charset == null){ charset = "utf-8"; } String responseStr = new String(response.body().bytes(), charset); response.body().close(); return new JSONObject(responseStr); } else if(response.code() == 401){ throw new InvalidCookie(); } else { return null; } } 

Если я попаду в каталог, который я назвал кешем для OkHttp, я могу увидеть файл журнала и еще 4 файла, содержащие ответы на некоторые из запросов. Этот запрос (/ api, который я только что вставил в код) хранится в каталоге кэша, поэтому он действительно кэшируется, но в конце файла имя файла имеет .tmp, например, если он не был должным образом сохранен в конечном файле , Как и другие просьбы, которые я сделал.

Вот как это выглядит как заголовки ответа сервера для запроса:

 HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Expires: Sat, 09 Aug 2014 19:36:08 GMT Cache-Control: max-age=86400, must-revalidate Last-Modified: Sun, 04 Aug 2013 15:56:04 GMT Content-Length: 281 Date: Fri, 08 Aug 2014 19:36:08 GMT 

И именно так OkHttp хранит его в кеше:

 {HOST}/api/0.3 GET 0 HTTP/1.1 200 OK 9 Server: Apache-Coyote/1.1 Expires: Sat, 09 Aug 2014 19:36:08 GMT Cache-Control: max-age=86400, must-revalidate Last-Modified: Sun, 04 Aug 2013 15:56:04 GMT Content-Length: 281 Date: Fri, 08 Aug 2014 19:36:08 GMT OkHttp-Selected-Protocol: http/1.1 OkHttp-Sent-Millis: 1407526495630 OkHttp-Received-Millis: 1407526495721 

После того, как OkHttp создает этот файл, он продолжает запрашивать у сервера тот же ресурс. Я вижу эти сообщения в Wireshark.

Что я делаю не так?

ОБНОВИТЬ:

Это ответ сервера после предложения Джесси:

 HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Expires: Thu, 14 Aug 2014 18:06:05 GMT Last-Modified: Sun, 10 Aug 2014 12:37:06 GMT Content-Length: 281 Date: Wed, 13 Aug 2014 18:06:05 GMT 

ОБНОВЛЕНИЕ 2: Пробовал версию кода и выяснил, что вполне вероятно, что есть ошибка в отношении кеша. Это то, что я получил от выхода Maven:

 Results : Failed tests: CacheTest.conditionalHitUpdatesCache:1653 expected:<[A]> but was:<[B]> Tests in error: CallTest.tearDown:86 » IO failed to delete file: C:\Users\Adrian\AppData\Local... Tests run: 825, Failures: 1, Errors: 1, Skipped: 17 

Более полный журнал можно увидеть здесь: https://gist.github.com/16BITBoy/344ea4c22b543f397f53

Solutions Collecting From Web of "Правильный способ настройки кеша для OkHttp в Android"

Я просто решил проблему. Это несколько вводило в заблуждение, что тесты кеша, где не удалось, когда я пытался использовать OkHttp из источника.

Проблема была довольно простой, и именно в том, что другие методы запроса получили тело на ответ, и он не был закрыт в конце. Это объясняет, почему я видел файл «.tmp» в кеше, но все же запутываю и вводил в заблуждение из-за того, что этот метод запроса потреблял и закрывал тело из ответа. Его как блокировка или монитор для редактора кеша является глобальным для всех запросов, а не по запросу. Я, хотя это не было, когда я читал код, когда он использовал хэш для запроса в качестве ключа.

Во всяком случае, это было так: D

С этого момента я попытаюсь придерживаться такого шаблона …

 String respBody = null; if(response.body() != null) { respBody = response.body().string(); response.body().close(); } 

… перед обработкой каждого случая для кода ответа. Таким образом, я не пропущу тесного вызова тела ответа.

Ваш сервер форсирует проверку кэша с помощью этого заголовка ответа:

 Cache-Control: max-age=86400, must-revalidate 

Удалите это, и вам должно быть хорошо идти.

У меня такая же проблема, затем я отлаживаю исходный код okhttp, вы можете посмотреть на CacheStrategy.cacheResponseAge () , okhttp будет использовать nowMillis и serveDate , serveDate получает от вас HTTP-заголовок сервера «Date», nowMillis получает С вашего устройства Android. Поэтому, когда время сервера меньше времени устройства, okhttp не будет получать кеш, если макс-возраст невелик.

Простите мой бедный английский ^ _ ^