以下内容整理自互联网,仅用于个人学习
1. Bitmap的存储位置
在Android2.3.3(API 10)及之前的版本中,Bitmap对象与其像素数据是分开存储的,Bitmap对象存储在Dalvik heap中,而Bitmap对象的像素数据则存储在Native Memory(本地内存)中或者说Derict Memory(直接内存)中,这使得存储在Native Memory中的像素数据的释放是不可预知的,我们可以调用recycle()方法来对Native Memory中的像素数据进行释放,前提是你可以清楚的确定Bitmap已不再使用了,如果你调用了Bitmap对象recycle()之后再将Bitmap绘制出来,就会出现Canvas: trying to use a recycled bitmap错误,而在Android3.0(API 11)之后,Bitmap的像素数据和Bitmap对象一起存储在Dalvik heap中,所以我们不用手动调用recycle()来释放Bitmap对象,内存的释放都交给垃圾回收器来做。
2. Bitmap导致的OOM
假如系统启动了垃圾回收线程去收集垃圾,而此时我们一下子产生大量的Bitmap对象,此时是有可能会产生OutOfMemoryError,因为垃圾回收器首先要判断某个对象是否还存活(JAVA语言判断对象是否存活使用的是根搜索算法GC Root Tracing),然后利用垃圾回收算法来对垃圾进行回收,不同的垃圾回收器具有不同的回收算法,这些都是需要时间的,发生OutOfMemoryError的时候,我们要明确到底是因为内存泄露(Memory Leak)引发的还是内存溢出(Memory overflow)引发的:
- 如果是内存泄露我们需要利用工具(比如MAT)查明内存泄露的代码并进行改正。
- 如果不存在泄露,换句话来说就是内存中的对象确实还必须活着,那我们可以看看是否可以通过某种途径,减少对象对内存的消耗,比如我们在使用Bitmap的时候,应该根据View的大小利用BitmapFactory.Options计算合适的inSimpleSize来对Bitmap进行相对应的裁剪,以减少Bitmap对内存的使用。
如果上面都做好了还是存在OutOfMemoryError(一般这种情况很少发生)的话,那我们只能调大Dalvik heap的大小了,在Android 3.1以及更高的版本中,我们可以在AndroidManifest.xml的application标签中增加一个值等于true的android:largeHeap属性来通知Dalvik虚拟机应用程序需要使用较大的Java Heap,但是我们也不鼓励这么做。
3. Bitmap的四种属性
图片压缩质量参数 枚举变量
- public static final Bitmap.Config ALPHA_8
- public static final Bitmap.Config ARGB_4444
- public static final Bitmap.Config ARGB_8888
- public static final Bitmap.Config RGB_565
ARGB指的是一种色彩模式,里面A代表Alpha,R表示red,G表示green,B表示blue, 其实所有的可见色都是红绿蓝组成的,所以红绿蓝又称为三原色,每个原色都存储着所表示颜色的信息值
- ALPHA_8就是Alpha由8位组成
- ARGB_4444就是由4个4位组成即16位,
- ARGB_8888就是由4个8位组成即32位,
- RGB_565就是R为5位,G为6位,B为5位共16位
由此可见
- ALPHA_8 代表8位Alpha位图
- ARGB_4444 代表16位ARGB位图
- ARGB_8888 代表32位ARGB位图
- RGB_565 代表8位RGB位图
4. Bitmap的使用
创建Bitmap的时候,Java不提供new Bitmap()的形式去创建,而是通过BitmapFactory中的静态方法去创建,如:BitmapFactory.decodeStream(is),通过InputStream去解析生成Bitmap。
在BitmapFactory中,我们可以很方便的通过BitmapFactory.Options中的options.inSampleSize去设置Bitmap的压缩比。
如果我们需要一次性加载大量的图片,我们不希望多次解析相同的Bitmap,也不希望可能不会用到的Bitmap一直存在于内存中,所以,这个场景下,Bitmap的重用变得异常的重要,Android提供BitmapFactory.Options.inBitmap的重用方式。