2012-04-30 2 views
2

Я должен поверить, что есть способ очистить данные изображения из памяти, как только это больше не требуется, но, несмотря на исчерпывающий поиск, я не могу найти решение. Оба стека и список разработчиков Google для Android имеют множество вопросов относительно ошибок OOM, в частности «размер растрового изображения превышает бюджет VM», но я до сих пор не вижу четкого ответа.удаление данных изображения из памяти

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

Например, представьте себе, это очень простое гипотетическое приложение, которое имитирует много поведения родной галереи приложения:

  1. галерея изображений, которая позволяет пользователю просмотреть изображения с удаленным сервера.
  2. На этом сервере может быть любое количество изображений.
  3. Приложение отображает 1 изображение за раз и позволяет пользователю возвращать или пересылать одно изображение за один раз нажатием кнопок или прокруткой.
  4. В любое время будет отображаться не более 3 изображений (так что пользователь может сразу увидеть изображение слева или справа от текущего изображения при прокрутке). Все остальные данные изображения должны быть отброшены.
  5. Изображения загружаются с использованием URL.openStream и Drawable.createFromStream или BitmapFactory.decodeStream. Потоки закрыты соответствующим образом.
  6. Изображения соответствуют размеру на сервере перед тем, как быть извлечены.
  7. Загрузка происходит в AsyncTasks. Задачи, которые больше не нужны (из-за перехода от изображения с неполной задачей), отменены. Любые ссылки в AyncTask являются WeaklyReferenced.
  8. Когда любое изображение больше не требуется, она не будет "очищен" с помощью:.
    • getBackground() setCallback (нуль)
    • Слушателей устанавливаются на нуль
    • setImageDrawable/Bitmap (нуль)
    • removeView

Эта простая конструкция, которая учитывает все методы предполагают, я знаю, будет неизбежно врезаться с OOM эр в какой-то момент. Использование BitmapFactory.Options inSampleSize и inPreferredConfig задержит неизбежное, но не навсегда, и за счет качества изображения. В этом примере я использовал удаленные изображения, но проблема существует с изображениями, хранящимися в/assets/или во внутренней памяти и т. Д.

Я чувствую, что если мы можем отображать X количество данных изображения в одной точке, и мы делаем все шаги для удаления данных изображения из памяти, мы должны иметь возможность отображать тот же самый объем данных позже, не компенсируя того, что произошло раньше.

С учетом большого количества вопросов по этому вопросу я бы надеялся, что стандартное решение будет задокументировано, но если оно есть, я не смогу его найти. Я видел ответы, опубликованные Роменом Гаем, который в противном случае кажется очень щедрым с его знаниями и активными в сообществе, которые говорят что-то вроде «Простой. Не используйте так много памяти». ОК. Скажи мне как.

Следует также упомянуть, что System.gc не делает ничего, чтобы помочь в этом. Я также знаю растровое изображение.но если я ошибаюсь, это нельзя использовать таким образом.

Я пропустил что-то фундаментальное? Есть ли способ сбросить данные изображения, если он больше не используется? Что отсутствует в приведенном выше примере, чтобы создать простую фотогалерею? Предполагая, что встроенное приложение галереи использует структуру, а не NDK, я полагаю, что должен быть способ ...

TYIA.

/этот вопрос также был опубликован в списке групп google разработчика Android.

ответ

3

Через мою работу с Prime Я нашел несколько советов, один из которых вы не упомянули. Когда вы декодируете свои растровые изображения, обязательно используйте флажки inPurgeable и inInputShareable в вашем BitmapFactory.Options. Это поможет немного, но я бы порекомендовал вам посмотреть на мою реализацию загрузки изображений в Prime. Я использую его во всех своих продуктах без каких-либо проблем с памятью. Я обнаружил, что 95% проблем с памятью связано с неправильным использованием класса Bitmap.

+0

Я обнаружил, что большинство сторонних загрузчиков заставляют использовать декодирование RGB_565, которое выглядит ужасно для некоторых изображений ... позволяет ваш класс ARGB_8888? У вас есть выборка (я не вижу никаких образцов на вашем репо, кроме одного 2-лайнера, хотя javadocs полезны, некоторые общие образцы были бы замечательными). Благодарю. – momo

+0

Я не форсирую формат. Примеры приведены в подпапке с надписью «примеры». Они также находятся в Google Play. – HandlerExploit

+0

Я проверю это - спасибо. – momo

-1

Существует очень detailed article об использовании растровых изображений на веб-сайте разработчика Android. Вы посмотрели? В нем объясняется, как эффективно загружать, кэшировать и отображать растровые изображения и как избавиться от этого знаменитого OutofMemoryError.

Существует также a sample application из галереи изображений. Я думаю, это то, что вы ищете.

+0

Я читал, что/эти статьи/s - it объясняет, как это сделать с большими растровыми изображениями (не применимо), как сделать это за пределами потока пользовательского интерфейса (который я уже делаю), как кэшировать (не применимо) и как визуализировать заставку (уже выполняется). Опять же, я могу * избежать ошибки, используя «трюки», но вопрос заключается в том, «как удалить это изображение из памяти». Спасибо за комментарий. – momo

Смежные вопросы