1

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

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

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

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

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

非常感谢。

以西结。

4

2 回答 2

1

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

特别是,您可能不得不使用“将缩小的版本加载到内存中”中的代码的修改版本,但我至少发现本节特别有用:

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));
于 2013-05-21T22:22:28.870 回答
0

您确定要加载同一个位图 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;
}
于 2013-05-21T21:58:57.450 回答