Android中经常会使用Bitmap,对于开发者来说,可以很方便的调用getByteCount() or getAllocationByteCount()函数,可以获取到大小,但是您思考过几个问题吗?
1)一张100px*100px的图片在内存中会占用多大内存?
2)内存中如何计算的?
3)getAllocationByteCount 与 getByteCount有什么不同吗?
1.占了多大内存?
Android中一张图片(Bitmap)占用的内存主要和以下几个因数有关:图片长度、图片宽度、单位像素占用的字节数、图片的像素密度、屏幕的像素密度。
计算方法:一张图片(Bitmap)占用的内存=(图片长度*targetdensityDpi/densityDpi)*(图片宽度*targetdensityDpi/densityDpi)*单位像素占用的字节数
长度和宽度不用多做解释 ,单位是像素;关键是单位像素占用的字节数如何获得呢?
这里不得不提一下Bitmap创建的API
Bitmap bitmap = BitmapFactory.decodeResource(Resources res,int id,BitmapFactory.Options opts);
单位像素占用的字节数由其参数BitmapFactory.Options的inPreferredConfig变量决定,默认为Bitmap.Config.ARGB_8888,它是个枚举类型,它可以为以下值
命名 | 描述 |
---|---|
ALPHA_8 | 此时图片只有alpha值,没有RGB值,一个像素占用1个字节 |
ARGB_4444 | 这种格式的图片,看起来质量太差,已经不推荐使用。一个像素占用2个字节,alpha(A)值,Red(R)值,Green(G)值,Blue(B)值各占4个bites,共16bites,即2个字节 |
ARGB_8888 | 一个像素占用4个字节,alpha(A)值,Red(R)值,Green(G)值,Blue(B)值各占8个bites,共32bites,即4个字节这是一种高质量的图片格式,电脑上普通采用的格式。它也是Android手机上一个BitMap的默认格式。 |
RGB_565 | 一个像素占用2个字节,没有alpha(A)值,即不支持透明和半透明,Red(R)值占5个bites ,Green(G)值占6个bites ,Blue(B)值占5个bites,共16bites,即2个字节.对于没有透明和半透明颜色的图片来说,该格式的图片能够达到比较的呈现效果,相对于ARGB_8888来说也能减少一半的内存开销。因此它是一个不错的选择。另外我们通过android.content.res.Resources来取得一个张图片时,它也是以该格式来构建BitMap的.从Android4.0开始,该选项无效。即使设置为该值,系统任然会采用 ARGB_8888来构造图片 |
所以一张100px*100px的图片在内存中占用的内存数为:
图片格式 | 计算公式 | 占用内存大小 |
---|---|---|
ALPHA_8 | 100*100 | 10000b |
ARGB_4444 | 1001002 | 20000b |
ARGB_8888 | 1001004 | 40000b |
RGB_565 | 1001002 | 20000b |
targetdensityDpi是指手机每英寸所有的像素点(比如三星S6,那就是640),densityDpi是图片所处的资源文件夹(比如是xxh,那就是480)
这几个参数的的解析,大家可以看一下下面两篇文章
https://zhuanlan.zhihu.com/p/20732309
https://www.cnblogs.com/yaozhongxiao/archive/2014/07/14/3842908.html
2.getAllocationByteCount 与 getByteCount有什么不同吗?
getAllocationByteCount 获取的是bitmap所占用的内存的大小,getByteCount获取的是bitmap根据上面规则所计算出的大小,正常情况下,这两者是相同的。但是有一种情况是图片复用
是会不一样
//开启图片的内存复用
options.inMutable=true;
如果一张bitmap加载开启这个option之后,代表内存可以复用,假设这张图片很大,那么下一张图片加载的时候,复用这块内存区域,就会造成getAllocationByteCount 与 getByteCount结果不同,因为前者返回的是bitmap所占用的实际内存的大小、后者返回的是图片的实际计算大小。
3.如何做好Bitmap的优化?
由上面的分析可从以下几点入手去优化Bitmap OOM相关问题:
1)大图小用,要记得抽样inSampleSize
2)小图大用,可以用矩阵Matrix
3)使用9.png代替其他图片
4)Bitmap如果经常同处加载,比如banner位置,可以考虑开启inMutable
5)想知道Bitmap实际宽和高,不必要加载到内存,可以通过inJustDecodeBounds,如果该 值设为true那么将不返回实际的bitmap,也不给其分配内存空间这样就避免内存溢出了。但是允许我们查询图片的信息这其中就包括图片大小信息
6)如果不需要透明度等信息时,使用RGB_565采样率
7)及时recycle
网友评论