Descarga asíncrona de mapas de bits en un adaptador, con énfasis en Bitmap.recycle ()

¿Podría alguien decirme cómo hacer un buen mecanismo para asíncrona. Descarga de imágenes para su uso en un ListView / GridView? Hay muchas sugerencias , pero cada una sólo considera un pequeño subconjunto de los requisitos típicos.

A continuación he enumerado algunos factores razonables (requisitos o cosas a tener en cuenta) que yo, y mis colegas, son incapaces de satisfacer a la vez.
No estoy pidiendo código (aunque sería bienvenido), sólo un enfoque que gestiona los mapas de bits como se describe.

  1. No hay duplicación de descargadores o Bitmaps
  2. Cancelación de descargas / asignación de imágenes que ya no se necesitarían, o es probable que se eliminen automáticamente (SoftReference, etc)
  3. Nota: un adaptador puede tener varias vistas para el mismo ID (las llamadas a getView (0) son muy frecuentes)
  4. Nota: no hay garantía de que una vista no se pierda en lugar de reciclarse (considere la posibilidad de cambiar el tamaño de GridView o Listar por texto)
  5. Una separación de puntos de vista y datos / lógica (tanto como sea posible)
  6. No iniciar un hilo separado para cada descarga (desaceleración visible de la interfaz de usuario). Utilice una cola / pila (BlockingQueue?) Y una agrupación de subprocesos, o algo así …. pero necesita finalizar que si la actividad se detiene.
  7. Purgar mapas de bits lo suficientemente alejados de la posición actual en la lista / cuadrícula, preferiblemente sólo cuando se necesita memoria
  8. Llamar a recycle () en cada Bitmap que se va a descartar.
  9. Nota: Es posible que la memoria externa no esté disponible (en todo o en todo momento) y, si se utiliza, debe borrarse (solo de las imágenes descargadas aquí) lo antes posible (considere la actividad destrucción / recreación de Android)
  10. Nota: Los datos pueden cambiarse: entradas eliminadas (selección múltiple y borrado) y agregadas (en un hilo de fondo). Los Bitmaps ya descargados deben mantenerse, siempre y cuando las entradas a las que estén vinculados todavía existan.
  11. SetTextFilterEnabled (true) (si se basa en el mecanismo de ArrayAdapter, afectará a los índices de la matriz)
  12. Utilizable en ExpandableList (afecta al orden en el que se muestran las miniaturas)
  13. (Opcional) cuando se descarga un mapa de bits, actualizar SOLAMENTE el ImageView relevante (los elementos de la lista pueden ser muy complejos)

No publique respuestas para puntos individuales. Mi problema es que cuanto más nos enfocamos en algunos aspectos, los otros más borrosos se convierten en Heisenberg .
Cada uno añade una dimensión de dificultad, especialmente Bitmap.recycle, que debe ser llamado durante la operación y en la destrucción de la actividad (tenga en cuenta que onDestroy, incluso onStop no se puede llamar).
Esto también impide confiar en SoftReferences .
Es necesario , o obtengo OutOfMemoryError incluso después de cualquier número de gc, sleep (20s, even), yield y enormes asignaciones de matrices en un try-catch (para forzar una OutOfMemory controlada) después de anular un Bitmap.
Estoy remuestreando los mapas de bits ya.

Compruebe este ejemplo. Como es utilizado por Google y también estoy usando la misma lógica para evitar el error OutOfMemory.

http://developer.android.com/resources/samples/XmlAdapters/index.html

Básicamente este ImageDownlaoder es su respuesta (ya que cubre la mayoría de sus requisitos) algunos que también puede implementar en eso.

http://developer.android.com/resources/samples/XmlAdapters/src/com/example/android/xmladapters/ImageDownloader.html

Al final, decidí ignorar completamente el error de reciclaje. Sólo añade una capa de dificultad imposible encima de un proceso manejable.
Sin esa carga (sólo haciendo que los adaptadores, etc dejen de mostrar imágenes), hice un administrador usando Map<String, SoftReference<Bitmap>> para almacenar los Bitmaps descargados bajo URLs.
Además, 2-4 AsyncTasks (haciendo uso de doInBackground y onProgressUpdate, se detiene añadiendo trabajos especiales que lanzan InterruptedException) tomando trabajos desde LinkedBlockingDeque<WeakReference<DownloadingJob>> soportado por un WeakHashMap<Object, Set<DownloadingJob>> .
El deque (código LinkedBlockingDeque copiado para su uso en la API anterior) es una cola en la que se pueden dejar trabajos si ya no son necesarios. El mapa tiene creadores de trabajos como claves, por lo que si un adaptador requiere descargas y luego se elimina, se quita del mapa y, como consecuencia, todos sus trabajos desaparecen de la cola.

Si la imagen ya está presente, un trabajo volverá sincrónicamente. También puede contener un conjunto de datos que pueden identificar la posición en un AdapterView que se refiere.

El almacenamiento en caché también se realiza en una tarjeta SD, si está disponible , bajo nombres URLEncoded. (Limpiado parcialmente, empezando por el más antiguo, en el inicio de la aplicación y / o usando deleteOnExit ()
Las solicitudes incluyen "If-Modified-Since" si tenemos una versión en caché, para buscar actualizaciones.

Lo mismo puede usarse también para el análisis XML y la mayoría de la adquisición de datos.
Si alguna vez limpiaré esa clase, pondré el código.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.