android - исключение нехватки памяти при создании растрового изображения - PullRequest
13 голосов
/ 18 апреля 2011

Я получаю следующую ошибку после повторного создания растрового изображения:

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  

Так как изображение огромно, я получаю ошибку. Но интересно то, что ошибка не возникает в первый раз, только когда я делаю снимок во второй раз, что заставляет меня поверить, что этот profileBitmap НЕ уничтожен. Как мне это убрать?

Ответы [ 9 ]

14 голосов
/ 24 ноября 2013

У меня была такая же проблема, и я решил ее следующим образом:

Мое приложение имело размер ~ 18 МБ, и когда я увидел, сколько памяти осталось свободным, я был шокирован - 654 КБ (на 1 ГБ ОЗУ!). Поэтому я просто удалил почти все изображения из проекта и загрузил их из Интернета при первом запуске, и при необходимости использую фотографии с SD-карты.

Чтобы проверить общую / свободную память для вашего приложения, используйте:

 Runtime.getRuntime().totalMemory();
 Runtime.getRuntime().freeMemory();

РЕДАКТИРОВАТЬ: я забыл главное - добавить в свой манифест, между тегом приложения, эту строку:

android:largeHeap="true"

13 голосов
/ 18 апреля 2011

Существует много проблем с исключениями памяти при растровых изображениях на Android, многие из которых обсуждаются в stackoverflow. Вероятно, было бы лучше, если бы вы просмотрели существующие вопросы, чтобы увидеть, соответствует ли ваш вопрос одному из существующих, а если нет, напишите, что отличает вашу ситуацию.

Некоторые примеры:

Исключение нехватки памяти из-за большого размера растрового изображения

Android: исключение из-за недостатка памяти в Галерее

Исключение из-за нехватки памяти в Android при обработке изображений

и т.д.: https://stackoverflow.com/search?q=android+out+of+memory+exception+bitmap

6 голосов
/ 05 июля 2016

Советы по обработке растровых изображений Android

Теперь вот несколько советов, которым вы можете следовать и которых можно избежать, из-за нехватки памяти в приложении Android.

  1. Всегда использоватьКонтекст деятельности вместо контекста приложения.потому что контекст приложения не может быть сборщиком мусора.И освободите ресурсы, когда ваша деятельность закончится.(жизненный цикл объекта должен совпадать с жизненным циклом).

2.Когда активность заканчивается.Проверьте HEAP DUMP (инструмент анализа памяти в Android Studio).

Если в 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;

Вышеуказанный фрагмент кода не даст нам никакого изображения / растрового изображения.для растрового объекта будет возвращаться ноль.но он определенно вернет ширину и высоту этого изображения.который является R.id.myimage.

Теперь у вас есть ширина и высота изображения.Вы можете увеличивать или уменьшать изображение на основе следующих факторов:

  • Размер ImageView, который будет использоваться для отображения изображения.
  • Доступный объем памяти.Вы можете проверить доступный объем памяти, используя ActivityManager и getMemoryClass.
  • Размер экрана и плотность устройства.

  • Использовать соответствующую конфигурацию растрового изображения

Если вы используете цветной канал RGB_565, который использует 2 байта на пиксель.половина выделения памяти для того же разрешения:)

Используйте свойство inBitmap для утилизации.

Не создавайте статический объект Drawable, так как его нельзя собрать мусором.

Запрос большой кучи в файле манифеста.

Используйте несколько процессов, если вы выполняете много обработки изображений (задача с интенсивным использованием памяти), или используйте NDK (Native Development используя c, c ++)

4 голосов
/ 13 мая 2012

Это происходит потому, что вы загружаете растровое изображение напрямую, которое занимает много памяти. Вместо этого используйте уменьшенную версию изображения в _profileBitmap. Этот парень объясняет это довольно хорошо. http://androidcocktail.blogspot.in/2012/05/solving-bitmap-size-exceeds-vm-budget.html

2 голосов
/ 19 сентября 2016

Вы можете использовать вектор Drawable. Он использует XML-файл для описания вашего изображения, поэтому он потребляет меньше памяти. Для этого вы должны использовать формат SVG для ваших изображений, а затем сгенерировать файл XML, используя одно из следующих 2 решений:

  • Решение 1. Используйте студию векторного ресурса в Android Studio: щелкните правой кнопкой мыши файл Drawable в вашем проекте -> новый -> векторный ресурс
  • Решение 2. Используйте веб-сайт svg2android: https://inloop.github.io/svg2android

Проверьте эту ссылку для получения дополнительной информации:
https://developer.android.com/studio/write/vector-asset-studio.html

2 голосов
/ 18 апреля 2011

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

1 голос
/ 03 августа 2018

У меня была эта проблема, потому что я изменял растровое изображение один раз, а затем изменял измененную версию второй раз, в результате чего три версии одного и того же растрового изображения (исходный плюс две измененные версии) находились в памяти одновременно.

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

1 голос
/ 29 октября 2015

С большими изображениями этого можно избежать, выбрав их в меньший размер.Пример использования ниже -

    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

0 голосов
/ 28 октября 2012

У меня была такая же проблема, когда телефон был выключен и снова включен.Просто установите для растровых изображений значение null и вызовите System.gc ();исправлены все проблемы.

...