忽略掉遥远的Android2.2及之前版本,本文讨论基于Android4.4,也适用于4.x版本。
         项目开发中遇到一个内存溢出问题,抓内存数据分析,发现有的bitmap在java层生成,占用的Dalvik虚拟机堆栈,这也符合我当前粗略的认知,恕本人知识浅陋。原来研究内存,一直认为Android2.2之后的各个版本Android中bitmap都是通过JNI回调到Java层,最后是在Java层真正new出来的bitmap(这个在本文最后取源码做了说明)。可是抓到的信息发现了一个Native stack上的Bitmap,如下图所示。

Android怎么生成200dpi的bitmap android createbitmap_源码分析


         然后查看资料和源码发现,的确这个是在Native Stack上创建的,因为它是调用BitmapFactory.decodeStream方法,创建出一个bitmap,decodeStream直接调用 JNI 的 nativeDecodeAsset() 来完成decode,这点不同于使用java层的createBitmap。所以这个是在Native层占用的内存。


private static Bitmap readBitMap(Context context, int resId) {  
        BitmapFactory.Options opt = new BitmapFactory.Options();  
        opt.inPreferredConfig = Bitmap.Config.RGB_565;  
        opt.inPurgeable = true;  
        opt.inInputShareable = true;  
        // 获取资源图片  
        InputStream is = context.getResources().openRawResource(resId);  
        return BitmapFactory.decodeStream(is, null, opt);  
    }

这里代码搬一下别人的代码来说明,如何做就在Native层生成Bitmap了,如上代码,

Options需要设置两个参数,  inPurgeable 、 inInputShareable为true。其实看源码分析,如果调用decodeStream方法,其实只要 inPurgeable 为true就够了,inInputShareable是默认为true的,不过别的方法就需要双双为ture,稍后源码分析详述此处。大家只要如上调用就可以让bitmap在Native上了。具体性能会不会有影响,稍后我会写几个demo验证一下。

         如图就是源码中的调用,图为BitmapFactory这个源码中decodeStream方法的具体实现,我们可以看到是调用的Native方法,可能有人会问了如果走了else呢,其实else里面的方法跟进去就会发现,也是做了一些处理后,调用nativeDecodeAsset来生成的bitmap。

Android怎么生成200dpi的bitmap android createbitmap_源码分析_02

说到这里我们必须说一个重要的事情,大家千万别以为去调用Native方法就一定是在Native层占用的内存,例如Bitmap.java中的createBitmap也是调用的JNI方法,但其实又反过来回调的Java中的New来做的生成操作。具体的这个地方,我会专门写一篇文章来讲Bitmap和BitmapFactory的源码,从源码中彻底分析一下为什么就是在Native中生成的。