2010-01-13 16 views
14

Tenía una pregunta relacionada con si (y cómo) debo almacenar las imágenes cargadas desde la web. Digamos que estoy llamando a un servicio web desde mi aplicación de Android. En este servicio web, recibo una URL para una imagen en la web. Descargo y muestro esta imagen en el lado izquierdo de un elemento de lista en un ListView. Mi pregunta es, ¿qué método debo usar para posiblemente almacenar la imagen? ¿Debo:Android - Almacenamiento de imágenes descargadas de la web

  1. guardarlo en la tarjeta SD, comprobando si existe cuando se crea el ListView (en las solicitudes posteriores) y volver a descargar según sea necesario (al actualizar la imagen de vez en cuando, en caso de que cambia).
  2. Almacénelo en la memoria caché utilizando Context.getCacheDir(), pero posiblemente forzándolo a volver a descargarlo con más frecuencia ya que no puedo confiar en la imagen que permanece en la memoria caché.
  3. Descárguelo siempre y nunca almacene la imagen.

Los archivos de imagen en sí son bastante pequeños, pero espero que algunos usuarios puedan tener docenas de estas pequeñas imágenes descargadas/almacenadas. ¿Cuál funcionaría mejor y/o cuál es el método preferido?

Como una pregunta complementaria, ¿debería cargar todas las imágenes en mi ListView primero (y posiblemente bloquear la IU durante algún tiempo) o cargarlas de forma asíncrona pero mostrar un marcador de posición mientras tanto (que podría ser un poco más " feo")? ¿Cuál es el estándar aquí?

+0

Considere también http://stackoverflow.com/q/1945201/1224741 – QED

Respuesta

21

Acerca de dónde almacenar: La respuesta depende de qué se está descargando y cuánto. Entonces haces una elección. Por ejemplo: Si está descargando algo que es temporal, menos en número (menos recuperaciones remotas) y tamaño (menos memoria) y es local para una actividad, entonces debería considerar mantener las imágenes en la memoria usando SoftReferences. SoftReferences puede llevar a reetiquetas, pero dado que la cantidad de elementos es pequeña, debe ser asequible.

Sin embargo, si el número de elementos a descargar excede un cierto umbral (lo que significa más recuperaciones y memoria) debería considerar reducir las capturas y también el consumo de memoria de tiempo de ejecución al almacenarlos en caché. Aquí puede elegir guardarlos en Sdcard o en almacenamiento temporal (directorios de caché locales a la aplicación). Para los elementos que son pequeños y tienen significado solo en el contexto de la aplicación (por ejemplo, miniaturas), el usuario en general no lo usará fuera de su aplicación. Entonces, puede almacenar tales cosas en el directorio de caché. La mejor parte de usarlos es que no tienes que limpiar el desastre. Se maneja automáticamente. Sin embargo, podría llevar a redestracciones.

Sin embargo, si los elementos descargados son de gran tamaño y pueden ser independientes fuera del contexto de la aplicación, como imágenes, video, clips de audio, entonces la tarjeta SD debería ser su opción. También debería leer: Handling large Bitmaps to avoid OOM error during BitmapFactory.decodeStream(..)

Tenga en cuenta que también se puede comprobar para ver si se utiliza una base de datos puede ayudar aquí. See this

Algunas consideraciones mientras perezosos artículos de carga en un ListView: que debe hacer la carga en segundo plano y no bloquear la interfaz de usuario thread.You debe considerar que muestra una imagen temporal mientras el elemento está siendo descargado. Esto es evidente en muchas aplicaciones nativas. Para una implementación de ejemplo de carga diferida see this. Además, para listas grandes, puede implementar el patrón SlowAdapter (comprobar demostraciones de API). Básicamente detiene la descarga mientras la lista se desplaza.

ejemplos de proyectos que pueden ayudarle aquí:

proyecto estantes de Romain individuo utiliza dos niveles de almacenamiento en caché en el que se emplea una caché en memoria (HashMap que contiene SoftReferences) y de almacenamiento en Sdcard. Browse Source code here

También hay algunas bibliotecas de código abierto que Mark Murphy escribió (CWAC) y DroidFu que pueden ayudar aquí.

¡Buena suerte!

3

En cuanto a su "pregunta complementaria", creo que cargarlos de forma asincrónica sería el comportamiento preferido, especialmente teniendo en cuenta que con transacciones de red, podría no ser simplemente "bloquear la IU durante algún tiempo" , pero "bloquea la UI permanentemente" en caso de que nunca se cargue.

Si considera que este comportamiento es feo, puede configurar un temporizador (1 o 2 segundos) que permita cargar algunas de las imágenes, y si se han cargado todas o el temporizador ha expirado, siga adelante y mostrar la IU de todos modos con imágenes de marcador de posición y dejar que el resto se cargue de forma asíncrona. Este sería el camino a seguir para evitar bloqueos permanentes de todos modos.

En cuanto a la primera parte de su pregunta, creo que depende en cierto modo del contexto y el tipo de imágenes que está mostrando. Sin embargo, con la mayoría de los recursos web, creo que el enfoque n.º 2 sería el preferido, ya que ciertamente no desea descargar varias veces en la misma sesión, pero probablemente tampoco quiera consumir almacenamiento permanente.

+0

Espero manejar las imágenes bastante bien, eliminarlas cuando ya no las necesite o el usuario borre los elementos relacionados a las imágenes. No espero que haya más de, digamos, 100 imágenes para un usuario muy pesado de mi aplicación. Buena idea con el temporizador antes de cargar las imágenes de forma asincrónica. Eso en realidad me llevó a otra línea de pensamiento: cargar suficientes imágenes para que los primeros elementos de la lista aparezcan correctamente, luego cargar el resto de forma asincrónica (posiblemente incluso mientras se desplazan hacia abajo). Gracias por eso. – Bara

+1

@Bara Eso es lo que quiero decir por contexto. Diría que si estas imágenes están relacionadas con algún tipo de actividad similar a la "navegación", solo querría almacenarlas en caché temporalmente. Si están relacionados con elementos permanentes que un usuario probablemente siempre verá cuando use su aplicación (como parece), probablemente no estaría de más utilizar los números 1 o 2. Me alegro de poder ayudar. – Nicole

+0

+1 para agregar contexto y verificar tipo en la cláusula de toma de decisiones! :) – Samuh

1

En lo que respecta a su "cuestión lado" - creo que cargarlos de forma asíncrona sería el comportamiento preferido, especialmente ya que es necesario tener en cuenta que con las transacciones de red, podría no sólo ser "bloquear la interfaz de usuario para algunos time ", pero" bloquea la UI permanentemente "en caso de que nunca se cargue.

Para evitar esto, si estamos hablando de WebImageView por Droid-fu se puede cambiar el ImageLoader.java initialize() para este

static int alive=-1; 
    public static synchronized void initialize(Context context) { 

     if (executor == null) {   
      executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(DEFAULT_POOL_SIZE);   
     } 
     else if(alive==executor.getActiveCount()){ 
       executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(DEFAULT_POOL_SIZE); 
      } 
     alive=executor.getActiveCount(); 
     if (imageCache == null) { 
      imageCache = new ImageCacheHope(context, 25, 5); 
     } 
    } 
0

escribí un Administrador de imágenes de Android que las manijas almacenamiento en caché de forma transparente (memoria y disco). El código está en Github https://github.com/felipecsl/Android-ImageManager

+0

Requiere demasiadas libretas externas. Quería usarlo, pero decidí hacerlo solo. – Makalele

Cuestiones relacionadas