Android - BitmapFactory.decodeByteArray - OutOfMemoryError (OOM) - PullRequest
4 голосов
/ 03 сентября 2011

Я прочитал сотни статей о проблеме ООМ. Большинство из них касаются больших растровых изображений. Я делаю картографическое приложение, где мы загружаем 256x256 плитки с наложением погоды. Большинство из них абсолютно прозрачные и очень маленькие. Я только что получил сбой в потоке растрового изображения длиной 442 байта при вызове BitmapFactory.decodeByteArray(....).

Исключительные состояния:

java.lang.OutOfMemoryError: bitmap size exceeds VM budget(Heap Size=9415KB, Allocated=5192KB, Bitmap Size=23671KB)

Код:

protected Bitmap retrieveImageData() throws IOException {
    URL url = new URL(imageUrl);
    InputStream in = null;
    OutputStream out = null;
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();

    // determine the image size and allocate a buffer
    int fileSize = connection.getContentLength();
    if (fileSize < 0) {
        return null;
    }
    byte[] imageData = new byte[fileSize];

    // download the file
    //Log.d(LOG_TAG, "fetching image " + imageUrl + " (" + fileSize + ")");
    BufferedInputStream istream = new BufferedInputStream(connection.getInputStream());
    int bytesRead = 0;
    int offset = 0;
    while (bytesRead != -1 && offset < fileSize) {
        bytesRead = istream.read(imageData, offset, fileSize - offset);
        offset += bytesRead;
    }

    // clean up
    istream.close();
    connection.disconnect();
    Bitmap bitmap = null;
    try {
        bitmap = BitmapFactory.decodeByteArray(imageData, 0, bytesRead);
    } catch (OutOfMemoryError e) {
        Log.e("Map", "Tile Loader (241) Out Of Memory Error " + e.getLocalizedMessage());
        System.gc();
    }
    return bitmap;

}

Вот что я вижу в отладчике:

bytesRead = 442

Таким образом, данные растрового изображения составляют 442 байта. Зачем пытаться создать растровое изображение размером 23671 КБ и не хватает памяти?

Ответы [ 3 ]

2 голосов
/ 03 сентября 2011

Я сталкивался с подобными проблемами в прошлом. Android использует Bitmap VM, и он очень маленький. Убедитесь, что вы используете свой битмап через bmp.recycle. Более поздние версии Android имеют больше битмап ВМ, но версия, с которой я имел дело, имеет ограничение в 20 МБ.

0 голосов
/ 02 февраля 2014

Звучит так, как будто вы уже читали эту тему, поэтому я избавлю вас от стандартных комментариев «Вот как вы расшифровываете растровое изображение».

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

Здесь есть отличное видео по Google I / O , которое действительно помогло мне, когда у меня возникли подобные проблемы.Это около часа, но, надеюсь, спасет вас через несколько дней.Он охватывает такие вещи, как:

  1. Создание дампов кучи
  2. Использование кучи в DDMS
  3. Использование MAT для сравнения / анализа дампов кучи
0 голосов
/ 13 сентября 2012

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

            Bitmap image;
   image = BitmapFactory.decodeByteArray(data, 0, data.length);
   Bitmap mutableBitmap = image.copy(Bitmap.Config.ARGB_4444, true);
   Canvas canvas = new Canvas(mutableBitmap); 

Мой старый ответ ниже, я не думаю, будет работать потоковое.

                Options options = new BitmapFactory.Options();
        Options options2 = new BitmapFactory.Options();
        Options options3 = new BitmapFactory.Options();

        options.inPreferredConfig = Bitmap.Config.ARGB_8888;///////includes alpha
        options2.inPreferredConfig = Bitmap.Config.RGB_565 ;///////no alpha
        options3.inPreferredConfig = Bitmap.Config.ARGB_4444 ;/////alpha lesser quality

        image=BitmapFactory.decodeResource(getResources(),R.drawable.imagename,options); 
        image=Bitmap.createScaledBitmap(image, widthx,height, true);  
...