一说到Bitmap,所以人都会想到回收,内存溢出等问题,我一直对Bitmap存在的实例化方法不太懂,现在就来看看。
大家都知道有个BitmapFactory类,该类有好多静态方法可以实例化一个Bitmap,看下源码知道, BitmapFactory对Bitmap的实例化最终都归到native层的方法来,我们看下所有的native方法
private static native Bitmap nativeDecodeStream(InputStream is,byte[] storage, Rect padding, Options opts); private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage, Rect padding, Options opts, boolean applyScale, float scale); private static native Bitmap nativeDecodeFileDescriptor(FileDescriptor fd,Rect padding, Options opts); private static native Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts); private static native Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts,boolean applyScale, float scale); private static native Bitmap nativeDecodeByteArray(byte[] data, int offset, int length, Options opts); private static native byte[] nativeScaleNinePatch(byte[] chunk, float scale, Rect pad); private static native boolean nativeIsSeekable(FileDescriptor fd);
可以看到主要有这几类
1::nativeDecodeStream , 2:nativeDecodeFileDescriptor,3:nativeDecodeAsset,4:nativeDecodeByteArray 方法可以解析出Bitmap对象
看下各个方法的源码,发现
1:decodeFile,decodeResourceStream,decodeResource这三种得到Bitmap对象的方法最终都会调用方法decodeStream来得到Bitmap对象,而decodeStream会根据图片源的不同,分别调用nativeDecodeStream或者nativeDecodeAsset方法来得到Bitmap对象。
2:decodeByteArray方法会调用nativeDecodeByteArray方法来得到Bitmap对象。
3:decodeFileDescriptor方法会调用nativeDecodeFileDescriptor方法来得到Bitmap对象。
还有一种方法可以实例化一个Bitmap对象,那就是Bitmap.createBitmap(),看下源码:最终会调用
private static Bitmap createBitmap(DisplayMetrics display, int width, int height, Config config, boolean hasAlpha) { if (width <= 0 || height <= 0) { throw new IllegalArgumentException("width and height must be > 0"); } Bitmap bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true); if (display != null) { bm.mDensity = display.densityDpi; } if (config == Config.ARGB_8888 && !hasAlpha) { nativeErase(bm.mNativeBitmap, 0xff000000); nativeSetHasAlpha(bm.mNativeBitmap, hasAlpha); } else { // No need to initialize it to zeroes; it is backed by a VM byte array // which is by definition preinitialized to all zeroes. // //nativeErase(bm.mNativeBitmap, 0); } return bm; }
最后还是调用native层的代码nativeCreate来创建一个Bitmap对象。
那么Bitmap对象被创建出来后,保存在哪里呢?这个问题,以后再研究。
现在我想做个实验,
实验1:对于一个ImageView显示图片,用xml中的src属性和background属性占用的内存有区别么,
经实验,发现Heap里面的Allocated分配内存一样大,答案:没区别。
实验2:用xml中的scr属性和用BitmapFactory解析出Bitmap然后在setImageBitmap到ImgeView中
占用的内存有区别么?经实验,发现Heap里面的Allocated分配内存一样大,答案:没区别。
实验3:给ImageView设置一张小图,然后铺满屏,和给ImageView设置一张大图,铺满屏,
占用内存有区别么?经实验,发现设置大图的情况下,Heap里面的Allocated分配的内存
比小图的时候要大的多,答案:设置大图的情况占用内存比设置小图的情况大多了。
实验4:给ImageView设置一张小图,一种铺满屏,一种保持本身大小,占用内存有却别么?
经实验,占用内存一样大。
实验5:同一张图片,jpg格式与png格式占用的内存是否相同?同一张图片的意思是只是用PS改了
下后缀名,jpg图片大小:512K, png图片大小:810K。经实验两张图片占用内存一模一样大。
结论:图片占用内存的大小跟图片显示出来的大小没有关系。一张图片不管你是放大还是缩小,它所占用的内存还是一样大,除非采用采样压缩图片的大小才会影响到图片对内存占用的大小。