Android 虚拟机默认为每个应用分配16M堆内存。ps:google原生OS的默认值是16M,但是各个厂家的OS会对这个值进行修改。

 

当在界面显示图片时,需要的内存空间不是按图片的实际大小来计算的,而是按像素点的多少乘以每个像素点占用的空间大小来计算的。图片加载到内存中需要把每一个像素都加载到内存中. 所以对内存的要求非常高, 一不小心就会造成OOM(OutOfMemoryError)错误。

假设:当前有一张图片,大小仅为1M,但是其规格(图片的像素)为3648*2736,那么完全加载此图片的像素数=3648*2736=9980928。在Android 中像素的表现形式有三种模式:

 

三种像素如下:

ARGB_4444 : 2bytes 每个像素占据2 个字节____A(Alpha)占4位的精度,R(Red)占4位的精度,G(Green)占4位的精度,B(Blue)占4位的精度,加起来一共是16位的精度,折合是2个字节,也就是一个像素占两个字节的内存,同时存储位图的透明度和颜色信息。不过由于该精度的位图质量较差,官方不推荐使用

ARGB_8888 : 4bytes 每个像素占据4 个字节____这个类型的跟ARGB_4444的原理是一样的,只是A,R,G,B各占8个位的精度,所以一个像素占4个字节的内存。由于该类型的位图质量较好,官方特别推荐使用。但是,如果一个480*800的位图设置了此类型,那个它占用的内存空间是:480*800*4/(1024*1024)=1.5M

RGB_565 : 2bytes 每个像素占据2 个字节____同理,R占5位精度,G占6位精度,B占5位精度,一共是16位精度,折合两个字节。这里注意的时,这个类型存储的只是颜色信息,没有透明度信息

 

假设采用ARGB_4444 模式作为像素的表现形式,则该1M大小的图片在Android 中占用的总空间为:

图片占用空间=总像素数*像素的单位

=9980928 *2bytes

=19961856bytes

=19M>16M

通过计算大家发现就算采用每个像素占用2 个字节的形式该1M 的图片也需要分配19M 的空间才能100%地将所有像素表现出来,这肯定会导致OOM 的发生。

 

解决方案:

通过代码可以对图片进行按比例(之所以按照比例缩放是为了避免图片的畸变,比如一张图片长度缩小一半,那么高度也缩小一半就保证了图片不会畸变)缩放,这也是必须要进行的工作。

假设:

图片的宽和高: 3648 * 2736

屏幕的宽和高: 320 * 480

计算缩放比:

宽度缩放比例: 3648 / 320 = 11

高度缩放比例: 2736 / 480 = 5

比较宽和高的缩放比例,哪一个大用哪一个进行缩放,因此我们采用11 作为该图片长和高的缩放比例。

计算缩放后的图片的宽和高:

宽=3648 / 11 = 331

高=2736 / 11 = 248

缩放后图片的宽和高: 331* 248

计算缩放后的图片在Android 中占有的空间:

总空间=331* 248*像素点大小=882088 * 2bytes=160K

最终计算结果是160K,远远小于堆内存的16M 上限,从而解决了OOM 的发生。