2016-08-24 3 views
-1

Я попытался загрузить свой пользовательский интерфейс, используя растровые изображения, получающие исключение OutOfMemory. Раньше я использовал PNG, затем я преобразовал их в GIF, чтобы уменьшить использование памяти, загрузив растровые изображения. Общее количество изображений составляет 291kb (при использовании PNG оно составляло около 2,2 МБ).Исключение OutOfMemory при загрузке пользовательского интерфейса через растровые изображения

Я использую этот код, используя inSampleSize для загрузки изображений, если изображения намного больше, чем размер экрана:

public void loadViewImage(View view, int drawableID) { 
     BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inJustDecodeBounds = true; 
     BitmapFactory.decodeResource(getResources(), drawableID, options); 
     options.inSampleSize = calculateInSampleSize(options, view.getWidth(), view.getHeight()); 
     options.inJustDecodeBounds = false; 
     view.setBackgroundDrawable(new BitmapDrawable(BitmapFactory.decodeResource(getResources(), drawableID, 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; 

    while (height/inSampleSize > reqHeight || width/inSampleSize > reqWidth) { 
     final int halfHeight = height/2; 
     final int halfWidth = width/2; 

     // Calculate the largest inSampleSize value that is a power of 2 and keeps both 
     // height and width larger than the requested height and width. 
     while ((halfHeight/inSampleSize) >= reqHeight 
       && (halfWidth/inSampleSize) >= reqWidth) { 
      inSampleSize *= 2; 
     } 
    } 

    return inSampleSize; 
} 

Изображение затем загружается через:

final RelativeLayout backgroundLayout = (RelativeLayout)findViewById(R.id.backgroundLayout); 
backgroundLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { 
     @Override 
     public void onLayoutChange(View v, int left, int top, int right, int bottom, 
            int oldLeft, int oldTop, int oldRight, int oldBottom) { 
      loadViewImage(backgroundLayout, R.drawable.background); 
     } 
    }); 

Это приложение работает на Samsung Galaxy S7 Edge, но не на LG G2. При использовании inSampleSize 2 это происходит, но мне интересно, как эти 291kb-изображения используют столько памяти.

Любая помощь очень ценится.

+0

Прежде всего, это гораздо более простой способ сделать это с помощью 'Picasso' для Android, или если вы по-прежнему хотите получить его по-своему, используйте все тяжелые логики для масштабирования и расчета битмапов от подсказки потока пользовательских интерфейсов' AsyncTask ' –

+0

* 291kb images * no, они не берут такого размера, когда они загружаются в виде растрового изображения ... еще раз: ** РАЗМЕР ФАЙЛА НЕ СОБИРАЕТСЯ ** – Selvin

+2

' Всего изображений 291kb'. Более уместно разрешение изображений. Поскольку использование растровых изображений в памяти зависит от разрешения. Теперь у вас нет разрешения под управлением, если вы используете BitmapFactory.decodeResource(), так как битмап будет адаптирован к screan. Вы можете лучше декодировать из обычного входного потока. – greenapps

ответ

0

Люди, говорящие вам размер, не имеют значения, это немного. Размер файла не имеет значения. Также GIF против JPG, против PNG. Каков размер изображения в пикселях. Объект Bitmap несжатый, а файлы сжимаются. Это означает, что он занимает 4 байта на пиксель (плюс некоторые накладные расходы, которые достаточно малы, чтобы их можно было игнорировать). Таким образом, изображение 1440x2560 составляет около 3,7 миллиона пикселей или около 15 МБ. Каждый из них занимает столько памяти. Масштабирование потребует большего - вам придется декодировать, по крайней мере, часть оригинала, чтобы масштабировать его (это может занять до суммы двух отдельных размеров).

Обычно, когда вы видите ошибки OOM, проблема заключается в том, как вы используете память по всему вашему коду, а не только в одном месте. Лучший способ проверить это с помощью профилирования кучи, ища сдерживание создания/сохранения объекта. Хотя очень большое изображение (например, изображение из 12-мегапиксельной камеры, распространенное на новых устройствах) может вызвать множество проблем при масштабировании - только изображение будет принимать 50 МБ. Если вы не загружаете много полноэкранных изображений, это не должно быть проблемой. Если это так, вы должны, вероятно, переработать их вручную. Если у вас много действий с такими макетами и может иметь глубокий стек, вы можете захотеть избавиться от изображений в onPause и перезагрузить inResume для сохранения памяти.

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