Android - исключение из памяти при создании растрового изображения
Я получаю следующую ошибку после создания растрового изображения во второй раз:
04-17 18:28:09.310: ERROR/AndroidRuntime(3458): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
this._profileBitmap = Bitmap.createBitmap(_profileBitmap, xCoor, yCoor, width, height);
Из журнала:
04-17 18:27:57.500: INFO/CameraCropView(3458): Original Photo Size: W 1536 x H 2048
04-17 18:28:06.170: INFO/CameraCropView(3458): xCoor: 291
04-17 18:28:06.170: INFO/CameraCropView(3458): yCoor: 430
04-17 18:28:06.170: INFO/CameraCropView(3458): Width: 952
04-17 18:28:06.170: INFO/CameraCropView(3458): Height: 952
Поскольку изображение огромно, я получаю ошибку. Но интересная вещь - ошибка не происходит в первый раз, только когда я делаю снимок второй раз, что заставляет меня поверить, что этот профильBitmap НЕ уничтожен. Как очистить это?
Ответы
Ответ 1
У меня была такая же проблема, и я решил ее следующим образом:
Мое приложение было размером ~ 18 МБ, и когда я увидел, сколько памяти осталось свободным, я был шокирован - 654 КБ (на 1 ГБ ОЗУ!). Поэтому я просто удалил почти все изображения из проекта и загрузил их из интернета при первом запуске, и при необходимости использовал картинки с SD-карты.
Чтобы проверить общую/свободную память для вашего приложения, используйте:
Runtime.getRuntime().totalMemory();
Runtime.getRuntime().freeMemory();
РЕДАКТИРОВАТЬ: я забыл главное - добавить в свой манифест, между тегом приложения, эту строку:
android:largeHeap="true"
Ответ 2
Есть много проблем с исключениями памяти с растровыми изображениями на Android, многие из которых обсуждаются в stackoverflow. Вероятно, было бы лучше, если бы вы рассмотрели существующие вопросы, чтобы узнать, соответствует ли ваша одна из существующих, а если нет, напишите, что отличает вашу ситуацию.
Некоторые примеры:
Исключение из памяти из-за большого размера растрового изображения
Android: исключение из памяти в галерее
Устранение неполадок с ОС Android при обработке изображений
и т.д.:
https://stackoverflow.com/search?q=android+out+of+memory+exception+bitmap
Ответ 3
советы по обработке битовых карт Android
Теперь вот советы, которые вы можете использовать, и можете избежать исключения из памяти в своем приложении для Android.
- Всегда используйте контекст действия вместо контекста приложения. потому что контекст приложения не может быть собранным мусором. И освободите ресурсы по мере завершения вашей деятельности. (жизненный цикл объекта должен быть
то же, что и для активности).
2. Когда активность завершается. Проверьте HEAP DUMP (инструмент анализа памяти в студии Android).
Если в HEAP DUMP есть объекты из готовой активности, происходит утечка памяти. просмотрите свои
кода и определить, что вызывает утечку памяти.
- Всегда использовать inSampleSize
Теперь что такое inSampleSize?
с помощью inSampleSize вы на самом деле говорите декодеру, чтобы он не хватал каждый пиксель в памяти, а не образ суб-образца.
Это приведет к меньшему количеству пикселей, которые будут загружены в память, чем исходное изображение. вы можете сказать, что декодер захватывает каждый 4-й пиксель или каждый второй пиксель от исходного изображения.
если inSampleSize - 4. декодер вернет изображение, равное 1/16 количества пикселей в исходном изображении.
Итак, сколько памяти вы сохранили? вычислить:)
-
Прочитайте размеры растровых изображений перед загрузкой в память.
Как читать размер растровых изображений перед загрузкой изображения в память может помочь избежать использования
ошибка памяти? Давайте учиться
использовать inJustBounds = true
вот техника, с помощью которой вы можете получить размер изображения, загрузив его в память
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
Более фрагмент кода не даст нам никакого изображения/растрового изображения. он вернет значение null для bitmap Object.
но он обязательно вернет ширину и высоту этого изображения. который является R.id.myimage.
Теперь у вас есть ширина и высота изображения. вы можете масштабировать или уменьшать изображение на основе этих факторов:
Конфигурации растровых изображений - это цветовое пространство/глубина цвета изображения. Конфигурация растрового изображения по умолчанию в Android - RGB_8888, которая составляет 4 байта на пиксель.
Если вы используете цветной канал RGB_565, который использует 2 байта на пиксель. половина распределения памяти для одного и того же разрешения:)
-
Используйте свойство inBitmap для целей утилизации.
-
Не создавайте статический объект Drawable, поскольку он не может быть собранным мусором.
-
Запросить большую кучу в файле манифеста.
-
Используйте несколько процессов, если вы выполняете большую обработку изображений (задача с интенсивной памятью) или используйте NDK (Native Development с использованием c, С++)
Ответ 4
Это происходит потому, что вы напрямую загружаете растровое изображение, которое потребляет много памяти.
Вместо этого используйте уменьшенную версию изображения в _profileBitmap.
Этот парень объясняет это довольно хорошо.
http://androidcocktail.blogspot.in/2012/05/solving-bitmap-size-exceeds-vm-budget.html
Ответ 5
Вы можете попробовать вызвать recycle() на растровом изображении, когда вы закончите с ним. Это очистит все данные изображения и освободит память. Если что-то попытается нарисовать растровое изображение после этого, ваше приложение выйдет из строя. Если вы столкнулись с крахом, это может помочь вам узнать, что все еще держит ваше растровое изображение.
Ответ 6
Вы можете использовать векторный Drawable. Он использует XML файл для описания вашего изображения, поэтому он потребляет меньше памяти.
Для этого вы должны использовать формат SVG для своих изображений, а затем сгенерировать файл xml с помощью одного из этих двух решений:
- Решение 1. Используйте студию векторных активов в Android Studio: щелкните правой кнопкой мыши на Drawable file в вашем проекте → new → vector asset
- Решение 2. Используйте веб-сайт svg2android: https://inloop.github.io/svg2android
Ознакомьтесь с этой ссылкой для получения дополнительной информации:
https://developer.android.com/studio/write/vector-asset-studio.html
Ответ 7
С большими изображениями его можно избежать, взяв образцы в меньшие размеры.
Используйте ниже пример -
File f = new File(selectedImagePath);
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, 720, 1280); //My device pixel resolution
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
Bitmap bmpPic = BitmapFactory.decodeStream(new FileInputStream(f), null, options);
Bitmap bmpPic1 = Bitmap.createBitmap(bmpPic, 0, 0, bmpPic.getWidth(), bmpPic.getHeight(), mat, true);
img.setImageBitmap(bmpPic1); //img is your ImageView
Справочно
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
Ответ 8
У меня была эта проблема, потому что я изменял растровое изображение один раз, а затем изменял измененную версию во второй раз, в результате чего три версии одного и того же растрового изображения (оригинал плюс две измененные версии) находились в памяти одновременно.
Я исправил это, изменив код редактирования изображения, чтобы применить обе модификации к одному и тому же растровому изображению в качестве своего рода пакетного процесса, сократив вдвое количество модифицированных версий, которые мое приложение должно было хранить в памяти.
Ответ 9
У меня была такая же проблема, когда телефон был выключен и снова включен. Просто установка растровых изображений на нуль и вызов System.gc(); исправлены все проблемы.