Android 默认为每个ImageView分配9x内存

Android allocates 9x memory for each ImageView as required by default

在将 ViewPager 和 运行 添加到一些 OutOfMemory 错误中时,我意识到我的默认方法 ImageView.setImageResource(resId) 导致分配的 RAM 比需要的多 9 倍。在我的示例中,我有一张 1920 x 1080 的图像,其原始分辨率略大于放置它的 ImageView 对象。我可以预期图像会缩小一些,但预计分配的空间不会超过 12.6 MB(1920 x 1080 x 4 字节)。但是,每个图像分配了 74.6 MB,并且加载了 4 个图像,这很快就耗尽了 VM 内存预算。

为了解决这个问题,我将方法更改为下面稍微长一些的代码 - 现在每张图片都准确分配了预期的本机内存量 (12.6 MB),并且图片仍然可以快速加载并且看起来很棒。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
options.inSampleSize = 1;
Bitmap bm = BitmapFactory.decodeResource(getResources(), resId, options);
mImageView.setImageBitmap(bm);

作为参考,我的设备是 Nexus 5,具有 1920 x 1080、xxhdpi、3 倍比例因子(dp 到像素)。我想象 OS 在内部将图像放大 3x3(=9x)以匹配缩放因子,但这没有意义,因为原始图像是全屏尺寸的原始分辨率。

他们最初分配这么多内存的原因是什么,是否有适当的方法设置图像资源来避免这种内存浪费?

drawable 文件夹中的可绘制对象被视为 mdpi(即 1x)。因此,系统会自动将图像放大到原始密度,在每个方向将其尺寸增大 3 倍,总共使用 9 倍的内存。

如果您希望系统将图像用作其原始分辨率,您应该将图像移动到 drawable-xxhdpi,并且系统将缩小图像以用于低密度设备。

如果您想要在所有密度上使用固定数量的像素(即,不同密度设备在屏幕上的物理尺寸不同),您可以使用 drawable-nodpi 文件夹。