Android Volley + JSONObjectRequest Almacenamiento en caché

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

Yo estaba esperando que este pedazo de código sería suficiente para mí para obtener el caché implícito de las respuestas. No estoy seguro si funciona o no, porque estaba bajo la suposición cuando se envía una solicitud:

  1. Golpearía la memoria caché primero y enviaría eso a la respuesta

  2. Entonces cuando los resultados vienen a través del servidor remoto que lo proporcionaría a la onresponse

Actualizar:

Me imaginé cómo recuperar manualmente el caché y reconstruirlo en un JSONObject y enviarlo a través de la función OnResponse, pero que no parece eficiente teniendo en cuenta que hay caché implícito. JsonObjectRequest clase debe devolver JSONObject como la entrada en caché en lugar de datos de respuesta sin formato.

Pero todavía estoy interesado en saber si estoy cometiendo algún error.

La ambigüedad es sólo debido a la falta de documentación, así que me disculpo si me falta algo muy obvio.

Ver esta respuesta – Establecer la política de vencimiento para el caché utilizando Google Volley

Esto significa que Volley decide si la respuesta en caché o no se basa sólo en los encabezados "Cache-Control" y luego "Caduca", "maxAge".

Lo que podría hacer es cambiar este método com.android.volley.toolbox.HttpHeaderParser.parseCacheHeaders(NetworkResponse response) e ignorar estos encabezados, establecer los campos entry.softTtl y entry.ttl a cualquier valor funciona para usted y utilizar su método en su solicitud clase. Aquí hay un ejemplo:

 /** * 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<String, String> 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; } 

Utilice este método en su clase de solicitud como esto:

 public class MyRequest extends com.android.volley.Request<MyResponse> { ... @Override protected Response<MyResponse> 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 proporciona códigos excelentes que pueden ayudarle cuando se trata de la estrategia de caché de Android Volley, especialmente cuando la API REST tiene encabezados de "Cache-Control" incorrectos o simplemente desea más control en su propia estrategia de caché de aplicaciones.

La clave es HttpHeaderParser.parseCacheHeaders(NetworkResponse response)) . Si desea tener su propia estrategia de caché. Sustitúyalo por parseIgnoreCacheHeaders(NetworkResponse response) en la clase correspondiente .

Si su clase extiende JsonObjectRequest, vaya a JsonObjectRequest y busque

 @Override protected Response<JSONObject> 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)); } } 

Y reemplazar HttpHeaderParser.parseCacheHeaders(response) con HttpHeaderParser.parseIgnoreCacheHeaders

+1 para oleksandr_yefremov y skyfishjy también, y ofreciendo aquí una clase concreta y reutilizable adecuada para json u otras API basadas en cadenas:

 public class CachingStringRequest extends StringRequest { public CachingStringRequest(int method, String url, Response.Listener<String> listener, Response.ErrorListener errorListener) { super(method, url, listener, errorListener); } public CachingStringRequest(String url, Response.Listener<String> listener, Response.ErrorListener errorListener) { super(url, listener, errorListener); } @Override protected Response<String> 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)); } } 

Donde la función parseIgnoreCacheHeaders () viene de la respuesta oleksandr_yefremov anterior. Utilice la clase CachingStringRequest en cualquier lugar que el json resultante esté bien en caché durante 3 minutos (en directo) y 24 horas (caducado pero aún disponible). Una muestra de solicitud:

 CachingStringRequest stringRequest = new CachingStringRequest(MY_API_URL, callback); 

Y dentro de la función onResponse () del objeto de devolución de llamada, analiza el json. Establezca los límites de almacenamiento en caché que desee – puede parametrizar para agregar caducidad personalizada por solicitud.

Por diversión, intenta esto en una aplicación sencilla que descarga json y procesa la información descargada. Después de haber llenado la caché con la primera descarga exitosa, observe la representación rápida mientras cambia las orientaciones mientras la caché está en vivo (no se realiza ninguna descarga debido a un error de caché en directo). Ahora, mata la aplicación, espera 3 minutos para que expire el caché (pero no 24 horas para que se elimine del caché), habilite el modo avión y reinicie la aplicación. Se producirá la devolución de llamada de error Volley y la devolución de llamada onResponse () se realizará desde los datos almacenados en caché, permitiendo que su aplicación redique contenido y también sepa / advierta que procede de la caché caducada.

Un uso de este tipo de almacenamiento en caché sería obviar Loaders y otros medios para hacer frente al cambio de orientación. Si una solicitud pasa por un Singleton de Volley y los resultados se almacenan en caché, las actualizaciones que ocurren a través del cambio de orientación se procesan rápidamente desde caché, automáticamente por Volley, sin el Loader.

Por supuesto, esto no se ajusta a todos los requisitos. YMMV

Fui capaz de forzar Volley para almacenar en caché todas las respuestas extendiendo StringRequest y reemplazando la petición que quiero forzar la caché con CachingStringRequest .

En el método anulado parseNetworkResponse quito Cache-Control encabezados de Cache-Control . De esta manera Volley está persistiendo la respuesta en su caché incorporado.

 public class CachingStringRequest extends StringRequest { private static final String CACHE_CONTROL = "Cache-Control"; public CachingStringRequest(int method, String url, Response.Listener<String> listener, Response.ErrorListener errorListener) { super(method, url, listener, errorListener); } @Override protected Response<String> 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); } } 
  • Android envía la solicitud de correos https al servidor sin métodos desaconsejados
  • Los anuncios de Google con varios tamaños de anuncio de DFP dan error
  • Android Volley almacena peticiones cuando está fuera de línea
  • ¿Hay alguna manera de cambiar el System User Agent de Genymotion Emulator?
  • Android httprequest java.net.UnknownHostException
  • Android - Volley RequestFuture Timeout
  • Interceptar solicitudes POST en un WebView
  • Hacer solicitud de volley en diferentes hilos
  • Cómo obtener el código de estado en la respuesta correcta Volley Android
  • Glide - agregar cabecera a la solicitud
  • Uso de la biblioteca AQuery con la solicitud PUT y StringEntity (String)
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.