深入探索Android Bitmap优化

对于Android内存优化,永远也绕不过Bitmap优化,作为Android中最能吃内存的对象之一,我们今天来深度剖析,从多个层面多个角度来优化bitmap。

基础知识

bitmap内存计算方式

理论上的内存大小:
图片占用内存 = 宽度像素 * 高度像素 * 单个像素占的字节数

bitmap 色彩模式

ALPHA_8: 每个像素占用1byte内存,代表8位Alpha位图
ARGB_4444:每个像素占用2byte内存,代表16位ARGB位图
ARGB_8888:每个像素占用4byte内存,代表32位ARGB位图
RGB_565: 每个像素占用2byte内存,代表16位RGB位图

Android 8.0之前bitmap内存分配

先说结论,我们再来从源码角度去分析:Android8.0之前(tips:这里指的是Android 2.3到Android 8.0之前,Android 2.3之前是放在native层的,不过生命周期不可控制,需要开发者自己手动控制,因为2.3之前版本太老,所以这里忽略)是把像素数据存储在java heap中的。

ok,我们来看Bitmap.java源码(这里源码基于Android 7.1.1):

一般我们通过createBitmap方法来创建一个bitmap对象:
在这里插入图片描述
接着我们沿着createBitmap方法不断的追踪下去我们会发现最后进入了这个createBitmap方法:
在这里插入图片描述
这里调用nativeCreate这个jni方法去获取了一个bitmap对象,ok我们继续跟踪到Bitmap.cpp中:
在这里插入图片描述
这里我们看到nativeCreate方法对应的是Bitmap_creator方法,跟进去:
在这里插入图片描述
在这里插入图片描述

Android 8.0之后bitmap内存分配

同样,先说结论,Android 8.0之后bitmap像素数据已经存到了Native层中,来看源码(这里源码基于Android 8.0):

Android5.0-7.0 bitmap放到Native内存操作实践

刚才已经讲过了,Android8.0之后源码里通过NativeAllocationRegistry这个类来复制回收Native层的内存,从而可以实现把bitmap的像素数据放到Native内存中并及时回收,那么如果我们想在Android 5.0-7.0版本中也把像素数据放到Native层可以么?
当然也是可以的。这里我说下我的思路:

// 步骤一:申请一张空的 Native Bitmap
Bitmap nativeBitmap = nativeCreateBitmap(dstWidth, dstHeight, nativeConfig, 22);

// 步骤二:申请一张普通的 Java Bitmap
Bitmap srcBitmap = BitmapFactory.decodeResource(res, id);

// 步骤三:使用 Java Bitmap 将内容绘制到 Native Bitmap 中
mNativeCanvas.setBitmap(nativeBitmap);
mNativeCanvas.drawBitmap(srcBitmap, mSrcRect, mDstRect, mPaint);

// 步骤四:释放 Java Bitmap 内存
srcBitmap.recycle();
srcBitmap = null;

这个方案有个缺点就是频繁的申请和释放java bitmap很容易造成内存抖动的情况,所以这个方案仅适用于少量bitmap的情况下,不适用于大量要用到大量bitmap的情况。

大图oom优化

当一个bitmap的宽和高大大超过view的宽和高的时候,这个时候你就要注意了,很容易产生大图oom的情况。

gif图片优化

gif图片如果按照Android原生的处理方法来加载的话,就会造成把gif下所有的图片一股脑全部加载到内存当中的尴尬,如果gif图片大一点的话,很容易出现oom的情况,所以gif图片的优化很关键。
我们来聊一下

猜你喜欢

转载自blog.csdn.net/jieqiang3/article/details/86533473