【问题标题】:Android Bitmap OutOfMemoryError [duplicate]Android位图OutOfMemoryError [重复]
【发布时间】:2013-05-16 18:13:32
【问题描述】:

我的 VSD220 出现 OutOfMemoryError(它是基于 Android 的 22 英寸一体机)

for (ImageView img : listImages) {
            System.gc();

            Bitmap myBitmap = BitmapFactory.decodeFile(path);
            img.setImageBitmap(myBitmap);
            img.setOnClickListener(this);
        }

我真的不知道该怎么办,因为这张图片低于最大分辨率。图像大小约为 (1000x1000),显示为 1920x1080。

有什么帮助吗? (那个 foreach 循环大约有 20 个元素,它在 6 或 7 个循环后被破坏..)

非常感谢。

伊泽奎尔。

【问题讨论】:

  • 我不同意将此标记为重复。在这个问题中,相同的图像在循环中重复加载。即使图像非常小,如果迭代次数足够多,也会出现内存不足错误。

标签: android bitmap imageview out-of-memory


【解决方案1】:

您应该查看Managing Bitmap Memory 的培训文档。根据您的操作系统版本,您可以使用不同的技术来管理更多位图,但无论如何您可能都必须更改代码。

特别是,您可能不得不使用“Load a Scaled Down Version into Memory”中代码的修改版本,但我至少发现这部分特别有用:

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



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

这种方法可以轻松加载任意大尺寸的位图 进入一个显示 100x100 像素缩略图的 ImageView,如图所示 以下示例代码:

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

【讨论】:

  • try { //此处导致 OutOfMemoryError 的代码 } catch (Error ee) { ee.printStacktrace(); }
【解决方案2】:

您确定要加载同一个位图 20 次吗?您不想加载一次并将其设置在循环中吗?

不过,无论屏幕分辨率如何,都不能保证加载 1000x1000 像素的图像。请记住,1000x1000 像素的图像占用 1000x1000x4 字节 =~4MB(如果将其加载为 ARGB_8888)。如果您的堆内存碎片/太小,您可能没有足够的空间来加载位图。您可能想查看BitmapFactory.Options 类并尝试使用inPreferredConfiginSampleSize

我建议您要么使用 DigCamara 的建议并确定尺寸并加载接近该尺寸的下采样图像(我说几乎是因为您不会使用该技术获得确切的尺寸),或者您尝试加载完整大小的图像,然后递归地增加样本大小(为获得最佳结果,增加两倍),直到达到最大样本大小或加载图像:

/**
 * Load a bitmap from a stream using a specific pixel configuration. If the image is too
 * large (ie causes an OutOfMemoryError situation) the method will iteratively try to
 * increase sample size up to a defined maximum sample size. The sample size will be doubled
 * each try since this it is recommended that the sample size should be a factor of two
 */
public Bitmap getAsBitmap(InputStream in, BitmapFactory.Config config, int maxDownsampling) {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize = 1;   
    options.inPreferredConfig = config;
    Bitmap bitmap = null;
    // repeatedly try to the load the bitmap until successful or until max downsampling has been reached
    while(bitmap == null && options.inSampleSize <= maxDownsampling) {
        try {
            bitmap = BitmapFactory.decodeStream(in, null, options);
            if(bitmap == null) {
                // not sure if there's a point in continuing, might be better to exit early
                options.inSampleSize *= 2;
            }
        }
        catch(Exception e) {
            // exit early if we catch an exception, for instance an IOException
            break;
        }
        catch(OutOfMemoryError error) {
            // double the sample size, thus reducing the memory needed by 50%
            options.inSampleSize *= 2;
        }
    }
    return bitmap;
}

【讨论】:

  • 对不起,我不想加载相同的图像 20 次,我想简化示例,我的真实代码由路径数组组成。所以图像不一样,但大小是一样的。我现在正在尝试你的答案,伙计们。在此之后我将再次发表评论。非常感谢!!
  • 非常感谢你们。它适用于这个缩略图,现在我必须显示全屏图像(在这种情况下为 1920x1024),并为它们制作一个画廊。我将尝试阅读 android 位图部分来做到这一点! developer.android.com/training/displaying-bitmaps/index.html
猜你喜欢
  • 2011-10-22
  • 2023-03-20
  • 2012-11-30
  • 2011-02-25
  • 1970-01-01
  • 1970-01-01
  • 2014-05-28
相关资源
最近更新 更多