解决Android加载大图片内存溢出的问题(OutofMemoryException)
首先解析一下基本的知识:
位图模式,bitmap颜色位数是1位
灰度模式,bitmap颜色位数是8位,和256色一样
RGB模式,bitmap颜色位数是24位 在RGB模式下,一个像素对应的是红、绿、蓝三个字节
CMYK模式,bitmap颜色位数是32位 在CMYK模式下,一个像素对应的是青、品、黄、黑四个字节
图像文件的字节数(Byte) = 图像分辨率*颜色深度/8(bit/8)
例如:一幅640*480图像分辨率、RGB色一般为24位真彩色,图像未经压缩的数据容量为:640X480X24/8=921600字节=900KB(1KB=l千字节=1024字节)。
注:一个图像文件占的磁盘空间大小还和磁盘的文件格式有关。如:NTFS最小单位为4KB 所以图像文件大小肯定是4KB的倍数。但是有图图片压缩算法的存在,图片文件在保存时,体积要比在内存的大小小得多,如640x480的图片文件大小一般只在200K~300K。这也是为什么,加载几MB的图片文件,会导致JVM内存溢出,导致OutofMemoryException的原因。
由上面的公式,我们可以得出,加载的图片所占的内存大小,取决于其分辨率和颜色数。
再了解一下,android读取解析图片的方式,基本与Java的方式类型,通过文件输入流,然后进行解码,再转成图片格式;
当然google的android也为我们封装好了若干方法,来方便快捷地完成这项工作,如ImageView的setImageBitmap,setImageResource,BitmapFactory的decodeResource等,但是尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图,因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存;
因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的source,加载显示。decodeStream最大的秘密在于其直接调用JNI-->nativeDecodeAsset()来完成decode,无需再使用java层的createBitmap,从而节省了java层的空间。
在使用decodeStream读取图片时,再加上Config参数,就可以更有效地控制加载目标的内存大小,从而更有效阻止抛OutofMemoryException异常,下面用一段代码说明:
if(!bmp.isRecycle() ){ bmp.recycle() //回收图片所占的内存 system.gc() //提醒系统及时回收 }