Retrofit ETAG y almacenamiento en caché

¿Hay una explicación adecuada sobre cómo agregar el almacenamiento en caché y el soporte ETAG / If-None-Match a Retrofit + OkHttp? Estoy luchando para añadir soporte Etag en 2 proyectos, y al principio sospecho que puede haber un problema con encabezados HTTP, otro proyecto tiene todo configurado correctamente y el almacenamiento en caché todavía no funciona como se esperaba.

Los siguientes son mis intentos de hacer que funcione. Los resultados muestran que el almacenamiento en caché parece estar funcionando dentro de la misma instancia de la aplicación, pero tan pronto como reinicie – todo carga mucho tiempo de nuevo. Además, en mis registros no vi If-None-Match se agregó a una solicitud, así que supongo que el servidor no es consciente de ETag y todavía recalcula la respuesta por completo.

Aquí hay algunos ejemplos de código:

 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())); } } 

El adaptador de descanso se crea con nivel de registro completo y una etiqueta personalizada:

 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(); 

Tengo una larga solicitud en la primera pantalla de la aplicación para la prueba. Cuando abro la aplicación, se tarda 7 segundos en completar la solicitud. Si hago una pausa y reanudar la aplicación, la misma solicitud tarda 250 ms, golpeando claramente la caché. Si cierro completamente la aplicación y la reinicio, vuelve a tomar 7 segundos.

UPDATE : Como se sugirió, he utilizado una construcción de Retrofit personalizada y adjunto un LoggingInterceptor. Esto es lo que estoy recibiendo.

 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 

Como puede ver, ningún encabezado If-None-Match está presente en la siguiente petición.

Veo que esta pregunta sigue recibiendo atención y tan pronto como no hay ninguna respuesta real que pueda elegir de – estoy proporcionando mi investigación sobre el tema y cerrar el hilo por ahora.

El resultado final de la investigación y algunas discusiones en los hilos de retrofit y okhttp en GitHub fue que supuestamente había un problema en OkHttp que podría evitar la etiqueta If-None-Match que se establecía para las solicitudes salientes.

El problema se suponía que se fijó en OkHttp 2.3, y estoy usando 'supuesto' aquí porque todavía no probar si realmente funciona. La prueba fue difícil porque estaba usando Retrofit, y Retrofit en sí tenía que ser actualizado para usar la nueva versión de OkHttp y añadir algunos nuevos Interceptors apoyo para poder depurar todos los encabezados que se establecen por OkHttp. El hilo relacionado está aquí: https://github.com/square/okhttp/issues/831

No estoy seguro si Retrofit fue actualizado después de eso. Esperemos que lo fuera, por lo que hay una buena probabilidad de que el problema ya está fijado y Etag debería funcionar correctamente – sólo asegúrese de tener las últimas versiones de Retrofit y OkHttp.

Intentaré probar todo yo una vez que tenga tiempo.

El uso de los interceptores OkHttp le ayudará a diagnosticar los encabezados que entran y salen de su aplicación. El documento de interceptores da un ejemplo de código de un interceptor que registra los encabezados de solicitud y respuesta en la red. Puede utilizar este as-es.

 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; } } 

Para conectarlo a Retrofit, necesitará una instantánea de pre-lanzamiento de Retrofit. A partir de enero de 2015, las versiones actuales de Retrofit no participan en los interceptores de OkHttp. Habrá un lanzamiento en breve que sí, pero aún no está listo.

Yo estaba teniendo un problema similar: OkHttp no golpear caché nunca, incluso cuando el servidor estaba enviando mismo ETAG.

Mi problema fue SIZE_OF_CACHE . Estaba definiendo un tamaño muy pequeño.

Intenta aumentarlo (algo así como 10 * 1024 * 1024 funciona para mí) También puedes explorar / data / data // files / cache para ver si realmente hay algo almacenado allí

  • Modificación retroactiva de caracteres especiales
  • Cargue archivos en el cubo AWS S3 usando OkHttp o Retrofit
  • POST Multipart Form Datos usando Retrofit 2.0 incluyendo imagen
  • Android: Realm + Retrofit 2 + Gson
  • ¿Cómo puedo hacer peticiones simultáneas más rápido con Retrofit / OkHttp?
  • Retrofit 2.0 lanzando "IllegalArgumentException: los parámetros @Field solo se pueden usar con la codificación de formularios". ¿Cómo hacer la consulta correcta de la API y arreglarlo?
  • Renovación de la referencia $ ref de objeto deserializante de JSON a su copia original
  • Deserialización GSON de una lista envuelta de objetos
  • RxJava onCompleted y onTerminate en el hilo principal
  • Android: agregando imagen al tweet usando la API REST de tela, Twitter y Retrofit
  • HTTPS no envía algunos encabezados de autenticación con Retrofit
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.