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

时间:2015-10-26 08:51:49

标签: android imageview android-bitmap

我正在尝试在ImageView中显示图库中的图像或捕获的相机。我开始在这个过程中获得OOM。所以我决定找出它是如何工作的。所以我尝试使用不同大小的图像进行观察,

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

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

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

2 个答案:

答案 0 :(得分:6)

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

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位精度存储。

答案 1 :(得分:2)

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

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

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

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

有关此内容的更多信息,请参阅开发者指南: https://developer.android.com/training/displaying-bitmaps/load-bitmap.html