Странная проблема OutOfMemory при загрузке изображения в объект Bitmap

Класс Android Training, «Displaying Bitmaps Efficiently», предлагает полезную outofmemoryerror информацию для понимания images и работы с исключением `java.lang.OutOfMemoryError: размер img растрового изображения превышает bitmap бюджет виртуальной машины android-framework при загрузке растровых изображений.


Считывание размеров и типа растрового изображения

Класс android-ui BitmapFactory предоставляет несколько android-bitmap методов декодирования (decodeByteArray(), decodeFile(), decodeResource() и outofmemoryexception т. д.) для создания Bitmap из различных android-ui источников. Выберите наиболее android-sdk подходящий метод декодирования img на основе вашего источника img данных изображения. Эти методы images пытаются выделить память image для созданного растрового android-bitmap изображения и поэтому могут img легко привести к исключению android-sdk OutOfMemory. Каждый тип метода декодирования android-framework имеет дополнительные сигнатуры, позволяющие image указать параметры декодирования outofmemoryexception с помощью класса BitmapFactory.Options. Установка outofmemoryexception для свойства inJustDecodeBounds значения true во out-of-memory время декодирования позволяет android-bitmap избежать выделения памяти, возвращая outofmemoryerror null для объекта растрового изображения, но out-of-memory устанавливая outWidth, outHeight и outMimeType. Этот image метод позволяет вам считывать images размеры и тип данных изображения android-sdk до построения (и выделения android-framework памяти) растрового изображения.

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;

Чтобы outofmemoryerror избежать исключений java.lang.OutOfMemory, проверяйте outofmemoryexception размеры растрового изображения image перед его декодированием, если picture только вы не полностью доверяете android-framework источнику, чтобы предоставить outofmemoryerror вам данные изображения предсказуемого android-sdk размера, которые удобно помещаются android-api в доступной памяти.


Загрузить уменьшенную версию в память

Теперь, когда picture размеры изображения известны, их img можно использовать, чтобы img решить, следует ли загружать android-framework в память полное изображение picture или вместо этого загружать outofmemoryexception версию с частичной выборкой. Вот android некоторые факторы, которые bitmap следует учитывать:

  • Расчетное использование памяти при загрузке полного изображения в память.
  • Объем памяти, который вы готовы выделить для загрузки этого изображения с учетом любых других требований к памяти вашего приложения.
  • Размеры целевого ImageView или компонента пользовательского интерфейса, в который должно быть загружено изображение.
  • Размер экрана и плотность экрана текущего устройства.

Например, не images стоит загружать в память outofmemoryerror изображение 1024x768 пикселей, если img оно в конечном итоге будет android-framework отображаться в виде эскиза android-ui 128x96 пикселей в ImageView.

Чтобы img декодер выполнял субдискретизацию images изображения, загружая меньшую android-framework версию в память, установите android-bitmap для inSampleSize значение true в своем объекте android BitmapFactory.Options. Например, изображение с android-framework разрешением 2048x1536, декодированное images с помощью inSampleSize, равного 4, дает picture растровое изображение приблизительно outofmemoryexception 512x384. Загрузка этого в img память использует 0,75 МБ bitmap вместо 12 МБ для полного android-sdk изображения (при условии, что out-of-memory растровая конфигурация ARGB_8888). Вот android-sdk метод вычисления значения android размера выборки, которое android-ui является степенью двойки android-ui на основе целевой ширины outofmemoryexception и высоты:

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) {

        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;
}

Примечание. Значение степени bitmap двойки вычисляется, потому outofmemoryerror что декодер использует окончательное outofmemoryexception значение путем округления img до ближайшей степени двойки android-framework в соответствии с inSampleSize документация.

Чтобы android использовать этот метод, сначала img выполните декодирование, установив img для inJustDecodeBounds значение true, pass the options through and then decode again using the new inSampleSize android-sdk value and inJustDecodeBounds set to false`:

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);
}

Этот android-bitmap метод упрощает загрузку растрового android-api изображения произвольно большого android-bitmap размера в ImageView, который отображает android-ui миниатюру размером 100x100 bitmap пикселей, как показано в picture следующем примере кода:

mImageView.setImageBitmap(
    decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

Вы image можете выполнить аналогичный android-api процесс для декодирования outofmemoryerror растровых изображений из images других источников, при необходимости android-sdk подставив соответствующий bitmap метод BitmapFactory.decode*.

android

image

bitmap

out-of-memory

android-bitmap

2022-11-20T04:42:36+00:00