Как динамически очистить или очистить память кучи в моем коде - PullRequest
6 голосов
/ 21 марта 2012

В моем приложении я использую простую галерею и coverflow, и у меня есть галерея изображений coverflow на изображении, нажатой в coverflow, я перенаправлен на следующее действие, которое содержит полноэкранную галерею, и я даже могу прокрутить мою полноэкранную галерею;но когда я добавляю больше изображений или изображений с высоким разрешением в мое приложение, оно принудительно закрывается из-за того, что размер растрового изображения превышает бюджет виртуальной машины

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

1 Ответ

31 голосов
/ 21 марта 2012

Вы не можете "очистить кучу". виртуальная машина сделает это автоматически, когда на ваши объекты больше не ссылаются.

Как говорится, растровые изображения - сложная вещь в Android. Объем памяти ограничен, и когда изображение декодируется в растровое изображение, оно может занимать гораздо больше памяти, чем сам формат сжатого изображения.

Нет простого ответа на ваше решение. Даже если вы все делаете правильно, у вас может просто не хватить памяти. При этом, вот несколько советов:

  1. Использовать Bitmap.release(). Битовые карты отличаются тем, что они размещаются в куче собственного стека (в отличие от виртуальной машины). Javadocs немного нечетки, говоря, что вам обычно не нужно называть это, но по моему опыту это «ключ» к виртуальной машине, который вы сделали с памятью, поддерживающей растровое изображение, важно. РЕДАКТИРОВАТЬ: Начиная с Android 3.0 (уровень API 11), данные пикселей хранятся в куче Dalvik вместе с соответствующим растровым изображением.

  2. Загрузка растровых изображений в память масштабируется . Вот сообщение в блоге на эту тему. Вы получаете только 24 МБ кучи на некоторых устройствах, и изображение с высоким разрешением может исчерпать все это, когда оно загружается в растровый объект. Обойти это невозможно, поэтому вы должны загрузить его в масштабе.

  3. Не звоните System.gc(), как сказал другой ответ. Люди, которые создали алгоритм GC, умнее вас и меня; Они знают, что делают. Вы никогда не получите OOME, когда есть память, которую можно освободить с помощью GC - GC всегда будет работать, прежде чем дать вам OOME.

  4. Это очевидно, но убедитесь, что у вас нет ссылок на растровые изображения, когда они больше не нужны.

  5. Наконец, и этот отстой, Android не выполняет сжатие кучи. Вот ТАК вопрос Я написал на нем некоторое время назад, без удовлетворительного ответа. Короче говоря, Android никогда не сжимает кучу, так как ваше приложение продолжает выделять большие или даже средние куски для растровых изображений, вы в конечном итоге окажетесь в ситуации, когда, хотя у вас нет нехватки памяти, нет достаточно больших смежных кусок памяти для вашего распределения, и вы получите OOME. только способ обойти это, как я уже писал в своем вопросе, состоит в том, чтобы убить процесс приложения, когда пользователь завершает работу. Это сделает запуск медленнее в следующий раз, но это гарантирует новую кучу. Не поймите меня неправильно, я не могу поверить, что это правильно, но никто не придумал лучшего решения.

...