时间:2021-05-19
由于Android对单个应用所施加的内存限制,比如16MB,这导致加载Bitmap的时候很容易出现内存溢出,本文主要包含2个方面的内容分析Bitmap内存和Bitmap高效加载
一、占用内存
获取bitmap的内存,android提供的方法bitmap.getByteCount()
假如现在mipmap-xhdpi 目录下,有一个 200 * 200 像素的图片,运行加载它,看它输出的尺寸。
Bitmap bitmap= BitmapFactory.decodeResource(getResources(),R.mipmap.btn_go);
bitmap.getByteCount()的输出结果为360000
现在把图片转移到mipmap-xxhdpi 中
bitmap.getByteCount的输出结果为160000
那么mipmap-xhdpi 目录下为何会大这么多呢?
density 影响 Bitmap 内存
放在不同的 mipmap 目录下,对应的不同 density 的设备。density 是设备的固有参数,伴随着 density 的,还有 densityDpi,它也是与设备相关的,表示屏幕每英寸对应多少个点(非像素点)
上面是官方提供的一张比较经典的图,可以看到,不同的目录,代表不同的 density ,例如 xhdpi 代表的 density 就是 2。而这里的 density 对 densityDip 的基准是 160 ,也就是说,mdpi 对应的 densityDpi 是 160 ,xhdpi 对应的 densityDpi 是 320,同样xxhdpi对应的densityDpi是480
density 和 densityDpi 在 Android 中,都有标准的 API 可以拿到,如下。
DisplayMetrics displayMetrics=new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);Log.i(TAG, displayMetrics.densityDpi+"");Log.i(TAG,displayMetrics.density+"");这是我手机的输出结果
从getByteCount()源码得知,Bitmap.getByteCount() 是由:
(bitmapWidth * scale) * (bitmapHeight * scale) *(每像素所占字节大小)得出来的
其中:int scale = phoneDensity / inDensity
phoneDensity是我们手机的densityDpi,上述得出我手机是480
inDensity是你图片存放的路径,比如xhdpi是320,xxhdpi是480
BitmapFactory默认色彩度为 ARGB_8888 图片,每像素会占用 4 bytes
在xhdpi下:200 * (480/320) * 200(480/320)4= 360000
在xxhdpi下:200 * (480/480) * 200(480/480)4= 160000
以上就是bitmap所占内存分析。
二、高效加载
1.修改bitmap.config
2.修改inSampleSize
bitmap.config简介
上面提到BitmapFactory默认色彩度为 ARGB_8888
Bitmap.Config一共有四个参数如下:
(这些参数决定了Bitmap位图的配置,会影响到bitmap的像素如何、色彩、以及是否有透明度的能力)
Bitmap.Config ALPHA_8
这个参数每个像素占用1字节的空间。
它代表每个像素点被存储为单个透明度的通道,这对于设置遮罩的图片用例十分有用,它不存储颜色信息。
Bitmap.Config RGB_565
这个参数每个像素占用2字节的空间。
它代表只有RGB通道的编码,其中红色占用5位地址,绿色占用6位地址,蓝色占用5位地址。没有透明度的通道。
使用不透明的位图时,不要求高的色彩保真度使用此配置是不错的选择。
Bitmap.Config ARGB_4444
这个参数每个像素占用2字节的空间。
它一共有四个通道,顾名思义,分别是透明度、红、绿、蓝。每个通道分别占用四位地址,所以一共2字节。
当应用需要节省内存(对色彩质量要求低),同时又需要存储透明度信息,这个配置可以作为选择,但官方比较推荐用ARGB_8888的设置,因为这个的色彩质量差。
Bitmap.Config ARGB_8888
这个参数每个像素占用4字节的空间。
这也是一共4个通道,但不一样的是每个通道站8位地址,因而色彩质量比上一个设置高了特别特别多(16倍)。
能够满足最好的位图质量,在内存充足的情况下,十分推荐使用这个。
inSampleSize简介
通过BitmapFactory.Options来缩放图片,主要是用inSampleSize参数,当inSampleSize=1时,采样后的图片为图片的原始大小,当inSampleSize=2时,采样后的图片宽,高均为原图大小的1/2,而像素数为原图的1/4,假定图片原有的内存是4MB,如果把它的inSampleSize设为2,它的内存就会变成1MB
具体实现代码如下
有了上面两个方法,实际使用就简单了,比如imageView所期望的图片大小为100X100,这个时候我们就可以这样调用,还是之前存放在xxhdpi中的图片,上述代码中已经把bitmap.config设置成ARGB_4444 ,现在把原先尺寸200X200改成100X100,看下内存是多少
bitmap.getByteCount的输出结果为20000,比之前160000减少了8倍, ARGB_4444较ARGB_8888减少了2倍,设置尺寸100,100传入setInSampleSize()方法中得到inSampleSize=2, 像素数为原图的1/4,内存大小总共就变成了之前的1/8,这样高效加载图片,就会远离oom。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
为什么要对Android中的图片进行采样缩放呢?是为了更加高效的加载Bitmap。假设通过imageView来显示图片,很多时候ImageView并没有图片的原
Android中屏幕密度和图片大小的关系详解前言Android中支持许多资源,包括图片(Bitmap),对应于bitmap的文件夹是drawable,除了dra
很多开发者表示,不知道Android的Drawable和Bitmap之间如何相关转换。下面Android123给大家两种比较简单高效的方法。 一、Bitm
AndroidLayoutInflater加载布局详解对于有一定Android开发经验的同学来说,一定使用过LayoutInflater.inflater()来
前言在Android开发过程中,Bitmap往往会给开发者带来一些困扰,因为对Bitmap操作不慎,就容易造成OOM(Java.lang.OutofMemory