// called from JNI
Bitmap(long nativeBitmap, byte[] buffer, int width, int height, int density,
boolean isMutable, boolean requestPremultiplied,
byte[] ninePatchChunk, NinePatch.InsetStruct ninePatchInsets)
通过构造函数的注释,得知这是一个给native层调用的方法,因此可以知道Bitmap的创建将会涉及到底层库的支持。为了方便从不同来源来创建Bitmap,Android中提供了BitmapFactory工具类。BitmapFactory类中有一系列的decodeXXX方法,用于解析资源文件、本地文件、流等方式,基本流程都很类似,读取目标文件,转换成输入流,调用native方法解析流,虽然Java层代码没有体现,但是我们可以猜想到,最后native方法解析完成后,必然会通过JNI调用Bitmap的构造函数,完成Java层的Bitmap对象创建。
// BitmapFactory部分代码:
public static Bitmap decodeResource(Resources res, int id)
public static Bitmap decodeStream(InputStream is)
private static native Bitmap nativeDecodeStream
native层的代码稍后我们在看,先从Java层来看看常规的使用。典型的一个例子是,当我们需要从本地Resource中加载一个图片,并展示出来,我们可以通过BitmapFacotry来完成:
Bitmap bitmapDecode = BitmapFactory.decodeResource(getResources(), resId);
imageView.setImageBitmap(bitmapDecode);
当然,这里简单的使用imageView.setImageResource(int resId)
也能实现一样的效果,实际上setImageResource方法只是封装了bitmap的读入、解析的过程,并且这个过程是在UI线程完成的,对于性能是有所影响的。另外,也对接下来讨论的内容,Bitmap占用的内存有影响。
Bitmap作为位图,需要读入一张图片每一个像素点的数据,其主要占用内存的地方也正是这些像素数据。对于像素数据总大小,我们可以猜想为:像素总数量 × 每个像素的字节大小,而像素总数量在矩形屏幕表现下,应该是:横向像素数量 × 纵向像素数量,结合得到:
Bitmap内存占用 ≈ 像素数据总大小 = 横向像素数量 × 纵向像素数量 × 每个像素的字节大小
单个像素的字节大小
单个像素的字节大小由Bitmap的一个可配置的参数Config来决定。
Bitmap中,存在一个枚举类Config,定义了Android中支持的Bitmap配置:
| Config | 占用字节大小(byte) | 说明 |
| — | — | — |
| ALPHA_8 (1) | 1 | 单透明通道 |
| RGB_565 (3) | 2 | 简易RGB色调 |