Кэширование Android Volley + JSONObjectRequest

public class CustomRequest extends JsonObjectRequest { public CustomRequest(String url, JSONObject params, Listener listener, ErrorListener errorListener) throws JSONException { super(Method.POST,url, params, listener, errorListener); this.setShouldCache(Boolean.TRUE); } } 

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

  1. он сначала попал бы в кеш и отправил это на ответ

  2. то, когда результаты будут получены с удаленного сервера, он предоставит его ответному ответу

Обновить:

Я решил, как вручную извлечь кеш и восстановить его в JSONObject и отправить его через функцию OnResponse, но это не кажется эффективным, поскольку существует неявное кэширование. Класс JsonObjectRequest должен возвращать JSONObject в качестве кэшированной записи вместо необработанных данных ответа.

Но мне все еще интересно узнать, не ошибаюсь ли я.

Неоднозначность объясняется только отсутствием документации, поэтому я извиняюсь, если я упускаю что-то совершенно очевидное.

См. Этот ответ. Установите политику истечения срока действия для кеша с помощью Google Volley

Это означает, что Volley решает, следует ли кэшировать ответ или нет, основываясь только на заголовках «Cache-Control», а затем «Expires», «maxAge».

Что вы можете сделать, это изменить этот метод com.android.volley.toolbox.HttpHeaderParser.parseCacheHeaders(NetworkResponse response) entry.softTtl com.android.volley.toolbox.HttpHeaderParser.parseCacheHeaders(NetworkResponse response) и игнорировать эти заголовки, установить entry.softTtl и entry.ttl для любого значения, которое работает для вас и использовать ваш метод в вашем запросе class. Вот пример:

 /** * Extracts a {@link Cache.Entry} from a {@link NetworkResponse}. * Cache-control headers are ignored. SoftTtl == 3 mins, ttl == 24 hours. * @param response The network response to parse headers from * @return a cache entry for the given response, or null if the response is not cacheable. */ public static Cache.Entry parseIgnoreCacheHeaders(NetworkResponse response) { long now = System.currentTimeMillis(); Map headers = response.headers; long serverDate = 0; String serverEtag = null; String headerValue; headerValue = headers.get("Date"); if (headerValue != null) { serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue); } serverEtag = headers.get("ETag"); final long cacheHitButRefreshed = 3 * 60 * 1000; // in 3 minutes cache will be hit, but also refreshed on background final long cacheExpired = 24 * 60 * 60 * 1000; // in 24 hours this cache entry expires completely final long softExpire = now + cacheHitButRefreshed; final long ttl = now + cacheExpired; Cache.Entry entry = new Cache.Entry(); entry.data = response.data; entry.etag = serverEtag; entry.softTtl = softExpire; entry.ttl = ttl; entry.serverDate = serverDate; entry.responseHeaders = headers; return entry; } 

Используйте этот метод в своем classе Request следующим образом:

 public class MyRequest extends com.android.volley.Request { ... @Override protected Response parseNetworkResponse(NetworkResponse response) { String jsonString = new String(response.data); MyResponse MyResponse = gson.fromJson(jsonString, MyResponse.class); return Response.success(MyResponse, HttpHeaderParser.parseIgnoreCacheHeaders(response)); } } 

oleksandr_yefremov предоставляет отличные коды, которые могут помочь вам, когда вы занимаетесь страtagsей кеширования Android Volley, особенно когда REST API имеет неправильные заголовки «Cache-Control» или вам просто нужно больше контролировать собственную страtagsю кеша приложений.

Ключ HttpHeaderParser.parseCacheHeaders(NetworkResponse response)) . Если вы хотите иметь собственную страtagsю кэширования. Замените его с помощью parseIgnoreCacheHeaders(NetworkResponse response) в соответствующем classе .

Если ваш class расширяет JsonObjectRequest, перейдите в JsonObjectRequest и найдите

 @Override protected Response parseNetworkResponse(NetworkResponse response) { try { String jsonString =new String(response.data, HttpHeaderParser.parseCharset(response.headers)); return Response.success(new JSONObject(jsonString),HttpHeaderParser.parseCacheHeaders(response)); }catch (UnsupportedEncodingException e) { return Response.error(new ParseError(e)); }catch (JSONException je) { return Response.error(new ParseError(je)); } } 

и замените HttpHeaderParser.parseCacheHeaders(response) с помощью HttpHeaderParser.parseIgnoreCacheHeaders

+1 для oleksandr_yefremov и skyfishjy также, предлагая здесь конкретный, многоразовый class, подходящий для json или других API на основе строк:

 public class CachingStringRequest extends StringRequest { public CachingStringRequest(int method, String url, Response.Listener listener, Response.ErrorListener errorListener) { super(method, url, listener, errorListener); } public CachingStringRequest(String url, Response.Listener listener, Response.ErrorListener errorListener) { super(url, listener, errorListener); } @Override protected Response parseNetworkResponse(NetworkResponse response) { String parsed; try { parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); } catch (UnsupportedEncodingException e) { parsed = new String(response.data); } return Response.success(parsed, parseIgnoreCacheHeaders(response)); } } 

где функция parseIgnoreCacheHeaders () исходит из ответа oleksandr_yefremov выше. Используйте class CachingStringRequest везде, где результирующий json может кэшировать в течение 3 минут (вживую) и 24 часа (истек, но все еще доступен). Образец запроса:

 CachingStringRequest stringRequest = new CachingStringRequest(MY_API_URL, callback); 

и в функции onResponse () объекта обратного вызова проанализируйте json. Задайте все ограничения кэширования, которые вы хотите – вы можете параметризовать, чтобы добавить пользовательское истечение за запрос.

Для удовольствия попробуйте это в простом приложении, которое загружает json и отображает загруженную информацию. Заполнив кеш первой успешной загрузкой, следите за быстрым рендерингом, когда вы меняете ориентацию, в то время как кеш живет (загрузка не происходит с учетом хита в реальном времени). Теперь убейте приложение, подождите 3 минуты, пока истечет срок его действия (но не 24 часа для его удаления из кеша), включите режим полета и перезапустите приложение. Будет вызван обратный вызов ошибки Volley, и «успешный» ответ на запрос onResponse () будет происходить из кэшированных данных, что позволит вашему приложению как отображать контент, так и знать / предупреждать, что он пришел из истекшего кеша.

Одним из способов такого кэширования было бы избавиться от Loaders и других средств борьбы с изменением ориентации. Если запрос проходит через Singleton Volley, и результаты кэшируются, обновления, которые происходят с помощью изменения ориентации, быстро отображаются из кеша автоматически с помощью Volley без Loader.

Конечно, это не соответствует всем требованиям. YMMV

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

В переопределенном методе parseNetworkResponse я parseNetworkResponse заголовки Cache-Control . Таким образом, Volley сохраняет ответ в своем встроенном кеше.

 public class CachingStringRequest extends StringRequest { private static final String CACHE_CONTROL = "Cache-Control"; public CachingStringRequest(int method, String url, Response.Listener listener, Response.ErrorListener errorListener) { super(method, url, listener, errorListener); } @Override protected Response parseNetworkResponse(NetworkResponse response) { // I do this to ignore "no-cache" headers // and use built-in cache from Volley. if (response.headers.containsKey(CACHE_CONTROL)) { response.headers.remove(CACHE_CONTROL); } return super.parseNetworkResponse(response); } } 
Interesting Posts

Как создать несколько папок и называть их, читая строки из текстового файла?

Почему «cd ..» работает в командной строке Windows?

Выберите случайное значение из enums?

перебирать все текстовые поля в форме, в том числе внутри группового windows

Swing Worker: функция get ()

Заполните оставшееся вертикальное пространство с помощью CSS с помощью дисплея: flex

Ошибка запуска службы WCF “Эта коллекция уже содержит адрес со схемой http”

HTTPS-запрос через AJAX с HTTP-страницы

Как узнать, имеет ли PNG-файл 24-битный цвет или 32-битный цвет в Mac OS X?

Почему Firefox не показывает правильный вариант выбора по умолчанию?

Какой графический API следует использовать с Azure AD B2C

Переход в начальную папку по умолчанию для командной строки Windows

Maven: команда для обновления репозитория после добавления зависимости от POM

Получить идентификатор вставленной записи: Php & MS SQL SERVER

В модели веб-программирования WCF можно написать рабочий контракт с массивом параметров строки запроса (то есть с тем же именем)?

Давайте будем гением компьютера.