Асинхронная загрузка растровых изображений в адаптере с акцентом на Bitmap.recycle ()

Может ли кто-нибудь сказать мне, как сделать хороший механизм для асинхронного использования. Загрузка изображений для использования в ListView / GridView? Есть много предложений , но каждый из них рассматривает только небольшое подмножество типичных требований.

Ниже я привел некоторые разумные факторы (требования или вещи, которые нужно учесть), которые я и мои коллеги не могут удовлетворить сразу.
Я не прошу код (хотя это было бы желательно), просто подход, который управляет битмапами, как описано.

  1. Нет дублирования загрузчиков или растровых изображений
  2. Отмена загрузки / назначения изображений, которые больше не нужны или могут быть автоматически удалены (SoftReference и т. Д.),
  3. Примечание. Адаптер может иметь несколько видов для одного ID (очень часто звонки на getView (0))
  4. Примечание: нет гарантии, что представление не будет потеряно вместо повторного использования (рассмотрите изменение / фильтрацию списка / GridView по тексту)
  5. Разделение представлений и данных / логики (насколько это возможно)
  6. Не запускать отдельный поток для каждой загрузки (видимое замедление UI). Использовать очередь / стек (BlockingQueue?) И пул потоков или что-то … но нужно прекратить это, если действие остановлено.
  7. Очистка растровых изображений, достаточно удаленных от текущей позиции в списке / сетке, желательно только тогда, когда требуется память
  8. Вызов recycle () для каждого Bitmap, который должен быть отброшен.
  9. Примечание. Внешняя память может быть недоступна (вообще или все время) и, если она используется, должна быть очищена (только загруженные здесь изображения) как можно скорее (рассмотрите уничтожение / восстановление активности Android)
  10. Примечание. Данные можно изменить: удаленные записи (multi-selection & delete) и добавлены (в фоновом потоке). Уже загруженные растровые изображения должны храниться до тех пор, пока записи, к которым они привязаны, все еще существуют.
  11. SetTextFilterEnabled (true) (если он основан на механизме ArrayAdapter, повлияет на индексы массива)
  12. Используется в ExpandableList (влияет на порядок отображения эскизов)
  13. (Необязательно) при загрузке Bitmap, ТОЛЬКО обновляйте соответствующий ImageView (элементы списка могут быть очень сложными)

Пожалуйста, не публикуйте ответы на отдельные вопросы. Моя проблема заключается в том, что чем больше мы фокусируемся на некоторых аспектах, тем более глухими другими становятся, как Гейзенберг .
Каждый из них добавляет измерение сложности, особенно Bitmap.recycle, которое необходимо вызвать во время работы и уничтожения активности (обратите внимание, что onDestroy, даже onStop, не может быть вызван).
Это также мешает полагаться на SoftReferences .
Это необходимо , или я получаю OutOfMemoryError даже после любого количества gc, sleep (20s, even), yield и огромных распределений массивов в try-catch (для принудительного управления OutOfMemory) после обнуления Bitmap.
Я уже передискретирую битмапы.

Solutions Collecting From Web of "Асинхронная загрузка растровых изображений в адаптере с акцентом на Bitmap.recycle ()"

Проверьте этот пример. Поскольку его используется Google, и я также использую ту же логику, чтобы избежать ошибки OutOfMemory.

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

В основном это ImageDownlaoder – это ваш ответ (поскольку он охватывает большинство ваших требований), которые вы также можете реализовать в этом.

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

В конце концов, я решил полностью игнорировать ошибку утилизации. Он просто добавляет слой невозможной трудности поверх управляемого процесса.
Без этого бремени (просто заставляя адаптеры и т. Д. Перестать показывать изображения) я создал менеджера, используя Map<String, SoftReference<Bitmap>> для хранения загруженных растровых изображений по URL-адресам.
Кроме того, 2-4 AsyncTasks (используя как doInBackground, так и onProgressUpdate, останавливаются добавлением специальных заданий, которые LinkedBlockingDeque<WeakReference<DownloadingJob>> InterruptedException), беря задания из LinkedBlockingDeque<WeakReference<DownloadingJob>> поддерживаемого WeakHashMap<Object, Set<DownloadingJob>> .
Код deque (код LinkedBlockingDeque, скопированный для использования в более раннем API) – это очередь, в которой задания могут покидать место, если они больше не нужны. На карте есть создатели заданий в качестве ключей, поэтому, если адаптер требует загрузки, а затем удаляется, он удаляется с карты и, как следствие, все его задания исчезают из очереди.

Работа будет, если изображение уже присутствует, возвращается синхронно. Он также может содержать Bundle данных, которые могут идентифицировать, какую позицию в AdapterView это касается.

Кэширование также выполняется на SD-карте, если она доступна , под именами URLEncoded. (Частично очищается, начиная с самого старого, при запуске приложения и / или используя deleteOnExit ()
Запросы включают «If-Modified-Since», если у нас есть кешированная версия, для проверки обновлений.

То же самое можно использовать и для синтаксического анализа XML и большинства других данных.
Если я когда-нибудь уберу этот класс, я отправлю код.