2013-08-23 2 views
7

Я использую android:background, чтобы получить фоновое изображение для макета Android.
После выкладывания изображения, которые я получаю это исключение:
OutOfMemory при загрузке большого фонового изображения

08-24 00:40:19.237: E/dalvikvm-heap(8533): Out of memory on a 36000016-byte allocation. 


, как я могу использовать большие изображения в качестве фона на Android?
Могу ли я расширить память кучи приложений? или это что-то нехорошо делать?

+3

Как упоминается во многих из этих вопросов, не используйте огромные (> 30 МБ в вашем случае) фоновые изображения. – kabuko

+2

В StackOverFlow есть много подобных вопросов. Я попытался сделать резюме многих альтернатив, чтобы решить эту проблему: http://stackoverflow.com/questions/11820266/android-bitmapfactory-decodestream-out-of-memory-with-a-400kb-file-with-2mb- f/16528487 # 16528487 –

+0

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

ответ

7

Пожалуйста, посмотрите на мой связанный с этим вопрос:

High resolution Image - OutOfMemoryError

Постарайтесь свести к минимуму использование памяти вашего приложения, сохраняя фоновое изображение как можно.

Это может быть сделано с помощью:

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

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

Убедитесь, что у вас есть только один экземпляр вашего растрового изображения в памяти. После его отображения вызовите recycle() и установите для ссылки ссылку null.

Это, как вы можете загрузить изображения:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, 
     int reqWidth, int reqHeight) { 

    // First decode with inJustDecodeBounds=true to check dimensions 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeResource(res, resId, options); 

    // Calculate inSampleSize 
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

    // Decode bitmap with inSampleSize set 
    options.inJustDecodeBounds = false; 
    return BitmapFactory.decodeResource(res, resId, options); 
} 

public static int calculateInSampleSize(
      BitmapFactory.Options options, int reqWidth, int reqHeight) { 
    // Raw height and width of image 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 

    if (height > reqHeight || width > reqWidth) { 

     // Calculate ratios of height and width to requested height and width 
     final int heightRatio = Math.round((float) height/(float) reqHeight); 
     final int widthRatio = Math.round((float) width/(float) reqWidth); 

     // Choose the smallest ratio as inSampleSize value, this will guarantee 
     // a final image with both dimensions larger than or equal to the 
     // requested height and width. 
     inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; 
    } 

    return inSampleSize; 
} 

Благодаря Adam Stelmaszczyk за этот прекрасный кусок кода.

+0

Эй, что вы имеете в виду, установив ссылку на null после использования растрового изображения? –

5

У меня возникла аналогичная проблема из-за фоновых изображений в макетах. Нормальный размер выделения памяти изображения должен быть высотой * шириной * 4 байта (в режиме ARGB_8888, режиме по умолчанию).

Если вы видите и выделяете 30 МБ при показе активности, должна быть какая-то проблема. Проверьте, размещаете ли вы фоновые изображения в папке с рисунком. В этом случае система должна масштабировать это изображение до определенной плотности экрана, вызывая большие издержки памяти.

Решение:

  1. Места конкретного варианта фонового изображения в каждой папке вытяжки (MDPI, ИПЧР, xhdpi ...).
  2. Поместите фоновое изображение в специальную папку ресурсов под названием «drawable-nodpi».Система не будет пытаться масштабировать изображения, размещенные в этом каталоге, поэтому выполняется только процесс растяжения и выделенная память будет ожидаемой.

Более подробная информация в этом answer

Надеется, что это помогает.

+0

Это сократило выделение графической памяти пополам! Спасибо! – Magritte

1

can I expand the application heap memory?

Да, вы можете. Просто установите android:largeHeap:="true" в свой Manifest.xml.

<application 
     android:name="com.pepperonas.libredrive.App" 
     android:allowBackup="true" 
     android:icon="@drawable/ic_launcher" 
     android:largeHeap="true" 
     android:label="@string/app_name" 
     android:launchMode="standard"> 
+0

Это не сработает, у приложений все еще может быть нехватка памяти, а также замедленное приложение вниз, с включенным largeHeap. https://developer.android.com/training/articles/memory.html Кроме того, большой размер кучи не одинаковый на всех устройствах, а при работе на устройствах с ограниченной оперативной памятью большой размер кучи может быть точно равен так же, как и обычный размер кучи. Поэтому, даже если вы запрашиваете большой размер кучи, вы должны вызвать getMemoryClass(), чтобы проверить размер обычной кучи и стремиться всегда оставаться ниже этого предела. – Nickmccomb

+0

Для меня эта функция разрешила проблему в фрагменте карты (который показывает маркер geo-маркера до 30 КБ) ... И да, понятно, что каждое устройство имеет ограниченную оперативную память - поэтому мы должны создавать код, который потребляет самые низкие доступные ресурсы (иногда лучше кэшировать данные, иногда рекомендуется использовать процессор). На данный момент никто не может дать короткий ответ. Но, как я уже сказал, этот фрагмент выше сделал трюк для меня в некоторых обстоятельствах .. так что неправильно говорить «это не работает». –

+0

Я не согласен. Я считаю, что решение не должно замедлять ваше приложение и вводить больше проблем в будущем. Приложение не работает, потому что оно плохо использует растровые изображения, вызывая ошибку Out Of Memory. Ваше «решение» не будет исправлять это, потому что, даже если растровое изображение находится под размером доступной памяти с вашим исправлением (чего может и не быть), после того, как будут введены новые растровые изображения, это определенно будет, и ошибка OOM все равно будет , Это не решение. – Nickmccomb

3

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

  1. Создать Drawable-nodpi папку и поместить фоновые изображения там.

  2. Использование Picasso для отображения изображений http://square.github.io/picasso/

отображать их с .Поставить() и .centerCrop() и Пикассо масштабирует изображение, если это необходимо

ImageView ivLogo = (ImageView) findViewById(R.id.ivLogo); 
Picasso.with(getApplicationContext()) 
    .load(R.drawable.logo) 
    .fit() 
    .centerCrop() 
    .into(ivLogo); 

Если вы делаете как-нибудь закончится память, Picasso просто не отобразит изображение, а не даст вам ошибку OOM. Надеюсь, это поможет!

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