WebViewClient shouldInterceptRequest Congela el WebView

Quiero almacenar en caché las imágenes que se muestran en el WebView durante un tiempo específico, por ejemplo, 7 días, así que necesitaba guardar las cachés de imágenes en el disco y cargarlas desde el disco y proporcionarlas al WebView.

También necesitaba cambiar el tamaño de las imágenes para evitar el WebView; Crash on High Memory Usage, por lo que implementé la lógica de caché y redimensionamiento en una función de bloqueo llamada " fetchBitmap ".

Como dice la documentación de Android, el " shouldInterceptRequest " se ejecuta en un Thread que no sea el UI Thread, por lo que puedo hacer networking en esta función, pero como puedo ver, una llamada de bloqueo hace que el WebView se congele.

La forma en que se comporta la función me obliga a usar una llamada de bloqueo , y no puedo pasar un Runnable para, por ejemplo, para una finalización futura.

¿Alguna solución?

webView.setWebViewClient(new WebViewClient() { private boolean isImage(String url) { if (url.contains(".jpg") || url.contains(".jpeg") || url.contains(".png")) { return true; } return false; } @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { if (isImage(url)) { Bitmap bitmap = ImageUtil.fetchBitmap(url); ByteArrayOutputStream bos = new ByteArrayOutputStream(); bitmap.compress(CompressFormat.JPEG, 100, bos); byte[] bitmapdata = bos.toByteArray(); ByteArrayInputStream bs = new ByteArrayInputStream(bitmapdata); return new WebResourceResponse("image/*", "base64", bs); } return null; } }); 

–ACTUALIZAR–

OK, he cambiado la lógica, ahora sólo bloqueo Leer desde el disco, y manejar la carga de la red (almacenamiento en caché) por separado en un ejecutables; " FetchBitmapForWebView "; Duplica la carga de la red cuando la caché no está disponible, pero la interfaz de usuario es ahora más sensible.

 public WebResourceResponse shouldInterceptRequest(WebView view, String url) { if (isImage(url)) { Bitmap bitmap = ImageUtil.fetchBitmapForWebView(url); if (bitmap == null) { return null; } ByteArrayOutputStream bos = new ByteArrayOutputStream(); bitmap.compress(CompressFormat.JPEG, 100, bos); byte[] bitmapdata = bos.toByteArray(); ByteArrayInputStream bs = new ByteArrayInputStream(bitmapdata); return new WebResourceResponse("image/*", "base64", bs); } return null; } 

El principio general es que usted no debe hacer ningún procesamiento pesado dentro de shouldInterceptRequest , ya que es una llamada síncrona (aunque en otro hilo). Las llamadas para todas las solicitudes de red se procesan en el mismo subproceso, por lo que el bloqueo de una solicitud hará que todas las demás solicitudes también se bloqueen.

Para su caso de uso, consideraría la posibilidad de ejecutar un pequeño servidor web dentro de su aplicación, que hará todo el almacenamiento en caché y procesamiento necesario. Seguramente, también tendrá que reescribir todos los vínculos dentro de las páginas web mostradas para poder volver al servidor local en lugar del servidor web original, por lo que puede ser engorroso en algunas situaciones. Pero como un enfoque general esto ayudará en gran medida con la descarga de trabajo pesado y el mantenimiento de una caché local.

Existen numerosos servidores web Java sencillos alrededor, por ejemplo:

  • ¿Cómo escondo un WebView?
  • Que cliente es mejor HttpURLConnection o HttpClient en android?
  • ¿Puedo ejecutar JavaScript sin un WebView, o un WebView puede ejecutarse sin un contexto de actividad, como en un servicio?
  • ¿Cómo llamar a un servicio web .NET desde android?
  • Android habilita el botón Atrás en la vista web
  • Android: Obtener la posición de desplazamiento de un WebView
  • Cookies HTTP WebView HTTP no funcionan en la API 21
  • Cómo seleccionar todo el contenido de WebView mediante programación?
  • Llamar al servicio web WSDL mediante el uso de retrofit android
  • Android - Elija el botón Archivo en WebView
  • ¿Cómo puedo encontrar la cantidad de datos que se transfieren cuando hago una llamada de servicio web desde mi aplicación android?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.