当前位置: 代码迷 >> Android >> 如何在Android中发生OOM(内存不足)?
  详细解决方案

如何在Android中发生OOM(内存不足)?

热度:134   发布时间:2023-08-04 12:04:16.0

我想在显示从画廊或捕捉的形式摄像机的图像ImageView 我开始在这个过程中获得OOM 所以我决定找出它是如何工作的。 所以我尝试了不同尺寸的图像,这里是观察,

我试图将19KB图像加载到ImageView并收到以下错误消息。 无法分配带有570452空闲字节的4915212字节分配和557KB直到具有2MB映像的OOM我无法分配具有16777120个空闲字节的31961100字节分配和29MB直到OOM 2MB

为什么19KB图像需要大约4.6MB的主内存和2MB图像需要30 MB的主内存空间?

PS:我发现很多解决方案,比如根据显示器对图像进行下采样,但没有一个解释这种行为。

理想情况下,您将使用ARGB_8888进行位图。 这意味着对于每个像素,分配4个字节(每个字节用于A,R,G,B)。 这意味着加载1024x768图像需要1024 * 768 * 4 = 3145728 B = 3072 KB = 3 MB。 这就是使用大容量内存的原因。 以下信息来自文档: :

Bitmap.Config.ALPHA_8 - 每个像素都存储为单个半透明(alpha)通道。

Bitmap.Config.ARGB_4444 - 此字段在API级别13中已弃用。由于此配置质量较差,建议使用ARGB_8888。

Bitmap.Config.ARGB_8888 - 每个像素存储在4个字节上。

Bitmap.Config.RGB_565 - 每个像素存储在2个字节上,只有RGB通道被编码:红色以5位精度(32个可能值)存储,绿色以6位精度(64个可能值)存储,蓝色以5位精度存储。

在Android中,图像的每个像素都需要4个字节的内存。 因此,如果您使用500万像素图像创建Bitmap ,则需要大约20MB。 因此,您应计算所需的样本大小,以便在不加载完整分辨率的情况下显示图像。

即使图像文件只有19KB, Bitmap对象也会占用更多内存。

尝试创建静态方法来计算所需的样本大小:

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

然后在加载完整图像之前先检查图像的边界:

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

有关这方面的更多信息,请参阅开发人员指南: :

  相关解决方案