Android – сохранение изображений, загруженных из Интернета

У меня возник вопрос о том, следует ли (и как) хранить файлы, загруженные из Интернета. Предположим, я звоню в веб-службу из своего приложения для Android. В этой веб-службе я получаю URL-адрес для изображения в Интернете. Я загружаю и показываю это изображение в левой части элемента списка в ListView. Мой вопрос: какой метод следует использовать для хранения изображения? Нужно ли мне:

  1. Сохраните его на SDCard, проверяя, существует ли он, когда создается ListView (при последующих запросах) и повторно загружается при необходимости (при одновременном обновлении изображения, если он изменяется).
  2. Храните его в кеше с помощью Context.getCacheDir (), но, возможно, придется повторно загружать его чаще, так как я не могу полагаться на изображение, находящееся в кеше.
  3. Всегда загружайте его и никогда не храните изображение.

Сами файлы изображений довольно малы, но я ожидаю, что некоторые пользователи могут иметь десятки этих маленьких изображений, загруженных / сохраненных. Что будет лучше всего работать и / или какой предпочтительный метод?

В качестве побочного вопроса, следует ли сначала загружать все изображения в свой ListView (и, возможно, блокировать пользовательский интерфейс в течение некоторого времени) или загружать их асинхронно, но показывать графику заметок (что может быть немного более «уродливым»)? Какой стандарт здесь?

Solutions Collecting From Web of "Android – сохранение изображений, загруженных из Интернета"

О том, где хранить: ответ зависит от того, что скачано и сколько. Тогда вы делаете выбор.

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

Однако, если количество загружаемых элементов превышает определенный порог (что означает больше выборок и памяти), вы должны рассмотреть возможность сокращения выборки, а также потребления памяти Runtime путем их кеширования. Здесь вы можете либо сохранить их на Sdcard, либо во временном хранилище (кэш-каталоги, локальные для приложения). Для объектов, которые являются малыми и имеют смысл только в контексте Приложения (например, миниатюры), пользователь в основном не будет использовать его вне вашего приложения. Таким образом, вы можете хранить такие вещи в каталоге кеша. Лучшая часть их использования заключается в том, что вам не нужно очищать беспорядок. Он обрабатывается автоматически. Однако это может привести к повторным выборам.

Однако, если загруженные элементы имеют большой размер и могут стоять отдельно от контекста приложения, такого как изображения, видео, аудиоклипы, то SDcard должен быть вашим вариантом. Вы также должны прочитать: Обработка больших растровых изображений, чтобы избежать ошибки OOM во время BitmapFactory.decodeStream (..)

Обратите внимание, что вы также можете проверить, может ли здесь помочь база данных. Видеть это

Некоторые соображения при ленивой загрузке элементов в ListView: вы должны выполнять загрузку в фоновом режиме, а не блокировать поток пользовательского интерфейса. Вы должны рассмотреть возможность отображения временного изображения во время загрузки элемента. Это очевидно во многих приложениях. Для примера рассмотрим реализацию ленивой загрузки. Кроме того, для больших списков вы можете реализовать шаблон SlowAdapter (проверить демонстрации API). Он в основном бросает кучу, пока список прокручивается.

Примеры проектов, которые могут вам помочь:

Проект Romain Guy's Shelves использует два уровня кэширования, в которых он использует кеш в памяти (HashMap, содержащий SoftReferences) и хранилище на Sdcard. Просмотреть исходный код здесь

Есть также некоторые библиотеки с открытым исходным кодом, которые Марк Марфи написал (CWAC) и DroidFu, которые могут помочь здесь.

Удачи!

Что касается вашего «бокового вопроса» – я думаю, что загрузка их асинхронно была бы предпочтительным поведением, тем более, что вам нужно учитывать, что с сетевыми транзакциями это может быть не просто «блокировка пользовательского интерфейса в течение некоторого времени», а «блокировка Пользовательский интерфейс постоянно "в случае, если он никогда не загружается.

Если вы считаете, что это уродливое поведение, вы можете установить таймер (1 или 2 секунды), который дает несколько изображений, которые можно загрузить, и если они все загружены или таймер истек, идите в UI В любом случае с изображениями-заполнителями, и пусть остальная загрузка выполняется асинхронно. В любом случае это будет способ предотвратить постоянные замки.

Что касается первой части вашего вопроса, я думаю, что она несколько зависит от контекста и типа изображений, которые вы показываете. Однако с большинством веб-ресурсов я считаю, что №2 будет предпочтительным, поскольку вы, разумеется, не хотите скачивать несколько раз в тот же сеанс, но вы, вероятно, тоже не хотите есть постоянное хранилище.

Что касается вашего «бокового вопроса» – я думаю, что загрузка их асинхронно была бы предпочтительным поведением, тем более, что вам нужно учитывать, что с сетевыми транзакциями это может быть не просто «блокировка пользовательского интерфейса в течение некоторого времени», а «блокировка Пользовательский интерфейс постоянно "в случае, если он никогда не загружается.

Чтобы избежать этого, если мы говорим о WebImageView от droid-fu, вы можете изменить функцию ImageLoader.java initialize () на это

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

Я написал Android Image Manager, который прозрачно выполняет кеширование (память и диск). Код находится на Github https://github.com/felipecsl/Android-ImageManager