很多搞android开发的搞了几年都搞不清这些细节,我也是糊里糊涂地过来的,今天特意来梳理一下,有错误的地方请留言指教。
假设有一张1080x480的png图片大小50k,加载到内存占有多大内存空间呢?
-
答案是不确定。要注意:这里看到的50k是pc上压缩后的图片大小,而android手机加载的图片显然不是压缩的图片,是要还原后的原图。至于怎么还原那是图片解压缩算法(或者说编解码算法)范畴了。
-
那需要多大内存空间呢?有关因素有:图片分辨率(图片宽高)、每个像素点大小(比如rbg和rbga格式大小不同吧)、如果是resource资源还与图片存放在哪个drawable目录有关。
-
那到底占用多大内存空间呢?
非drawable资源图片:占用内存空间大小 = 每个像素大小 x 图片宽度 x 图片高度 = 每个像素大小 x 分辨率 drawable资源图片:占用内存空间大小 = 每个像素大小 x 相对宽度 x 相对高度 相对宽度 = 图片宽度 x (手机设备像素密度 / drawable-xx目录对应的像素密度 ) 相对高度 = 图片高度 x (手机设备像素密度 / drawable-xx目录对应的像素密度 ) drawable-xx目录对应的像素密度值,如下: 标准值为mdpi=160,hdpi=1.5x160=240,xdpi=2x160=320,xxdpi=3x160=480 真实手机设备像素密度值怎么计算呢?如下: 手机像素密度值 = 手机对角线上多少个像素 / 手机对角线上多少英寸
-
下面是举例子说明一张图片加载到内存的计算:
假设有一张1080x480的png图片, 其原始大小为:1080x480x4B=2073600B=1.98MB //rgba各占1B pc上看到的是压缩图片,可能也就50k左右,相差那么多呢。。 如果这张图片是从非drawable-xxx目录比如文件网络等地方加载的,不做任何裁剪压缩等操作,加载到内存需要大约1.98MB。 如果这张图片放在drawable-mdpi目录下,从这个目录加载的呢?那么其占用内存大小计算如下: drawable-mdpi目录对应的像素密度值为160, 假设一部手机比较高端像素密度值为xxdpi即480, 那么这张图片加载到内存不做裁剪压缩等处理,占用的大小为: dw = 1080x(480/160) = 1080x3 = 3240 dh = 480x(480/160) = 480x3 = 1440 size = 3240x1440x4B = 18662400B = 17.8MB 可以看出:放在密度比较低的drawable-xx下,加载到密度比较高的手机上时,内存占用是很大的,要特别注意。 如果这张图片放在drawable-xxdpi目录下,从这个目录加载的呢?那么其占用内存大小计算如下: drawable-xxdpi目录对应的像素密度值为480, 假设一部手机比较低端像素密度值为mdpi即160, 那么这张图片加载到内存不做裁剪压缩等处理,占用的大小为: dw = 1080x(160/480) = 1080/3 = 360 dh = 480x(160/480) = 480/3 = 160 size = 360x160x4B = 230400B = 225KB 可以看出:放在密度比较高的drawable-xx下,加载到密度比较低的手机上时,内存占用是很小的,但图片往往比较模糊。
-
通过上面的计算例子可以看出,在权衡图片模糊程度后往往选择将图片放在密度比较高的drawable-xx目录下,比如drawable-xxdpi目录下。这样可以避免高端手机加载图片时占用过多内存,低端手机又能看清楚可以接受即可。
-
实际项目开发里,往往会对图片做适当的裁剪压缩等操作,在视觉上可以接受的情况下想方法尽可能减少图片加载到内存所占的空间。android在api层面给我们提供了BitmapFactory.Options来处理这个问题。
-
如何获取图片加载到内存的大小,我使用的是bitmap.allocationByteCount方法获取的。
-
手机像素密度具体可以参考:具体参考