在Android开发中Bitmap确定是绕不过去的,不少时候咱们只是使用图片框架加载图片,具体细节的Bitmap对内存的使用图片框架已经帮咱们封装好了。可是对Btimap对内存的影响咱们仍是须要了解的。html
首先要清楚Bitmap的文件大小确定不是实际的内存加载大小。由于文件只是存储的信息,加载到内存中显示出来时还须要通过转换。android
获取运行的时的内存占用: 针对Bitmap位图对象,Android的系统框架中的graphics包下的BItmap类。有bitmap.getByteCount()
方法获取内存大小,单位字节(byte) 其实本质上Bitmap的内存占用计算很是简单:网络
基本公式:总内存=宽×高×色彩空间框架
可是在实际运行中不是这么简单,公式的每一个参数都会有被不一样因素影响。ide
咱们这里不从代码出发,直接说重点不会云山雾罩的。 之前文的公式为基础。 影响内存大小的三要素优化
咱们在AS打开图片看到的文件信息 .net
做用:宽高的乘积描述图片的像素点总数,也就是这个图片由多少像素构成。code
它通常不是咱们最终加载到内存时的图片宽高,可是能够认为是基础变量。orm
即Bitmap.Config枚举:cdn
做用:色彩空间描述每一个像素点的信息
总共32位(4byte),分别对应4个数值,数值单位为8bit位=1byte字节,分别描述透明度(1个)+RGB通道(3个)。每一个字节数值范围0-255。做为Bitmap配置色彩空间的默认值。BitmapFactory加载时默认。 public Bitmap.Config inPreferredConfig = Bitmap.Config.ARGB_8888
总共16位(2byte),分别对应3个数值,5位(红)+6位(绿)+5位(蓝)分别描述RGB通道。Glide加载时默认使用,DecodeFormat类 public static final DecodeFormat DEFAULT = PREFER_RGB_565
能够看到,RGB_565只须要ARGB_8888的一半大小,代价是没有透明度描述。
做用:对图片原始宽高的缩放设置认定为缩放比。
首先须要指出,缩放比在内存的影响上是次方的,影响值=缩放比×缩放比。这是由于缩放比分别做用在宽高上,使用了两次。 缩放比会被不少因素影响。
在解析Bitmap时,有个可选的Options对象,其中inSampleSize
参数能够影响缩放比的结果。当使用该参数值时要求大于1且是2的倍数,好比在inSampleSize=2
时,缩放比被缩小2倍(该功能只有缩小没有放大的可能),即“缩放比=原始缩放比×(1/2)”。对内存结果的影响是缩小4倍,由于宽/高都被缩小2倍。该值默认不生效,须要手动设置。
在系统中主要由,具体运行设备dpi的和图片文件存储的drawable文件dpi层级决定。 首先要引出屏幕密度概念。这是Android为应对众多的不一样的屏幕分辨率色设备提出的概念和单位。
设备和drawable文件的dpi缩放比计算: 好比drawable-xhdpi(320=2160=2mdpi)下的bitmap被加载到xxxhdpi(640=4160=4mdpi)的Pixel-XL中。 dpi缩放比=设备dpi/drawable的dpi,因此上面的,dpi缩放比=640/320=2。 实际意义就是在高分辨率的xxxhdpi设备中,drawable-xhdpi文件须要放大2倍,即宽高各放大2倍来适应高密度设备。须要指出的是若是Bitmap文件保存在drawable没有后缀的文件中,系统会使用drawable的dpi默认层级就是160;
须要说明的是:这个缩放比只在当Bitmap文件位于drawable这样有dpi层级的文件中时生效。若是Bitmap位图文件位于assets包这样的外部文件或者是URL网络地址,是有没有缩放比的(即默认为1)不影响内存结果。这个也好理解,当读取文件时得不到其余的信息就不须要再处理了。有趣的是Glide也是存在缩放比概念的,可是和dpi无关,和View视图有关。
Glide缩放比=View视图值/原图值 ,这里的值是不固定的,由于缩放比只有一个,可是视图宽高和原图宽高的比值有两个,须要权衡取出可以同时应用于宽高的缩放比。
最后的缩放比结果:
缩放比=主动设置缩放比*被动设置缩放比
主动缩放比:没有设置时,默认为1,即不影响另外的值。 被动缩放比:这须要看能不能获得设备和drawable的关系(或者其余关系,如Glide的视图图片比例)若是不能获得也是1。
基于以上认识,丰富上文的基本公式,能够的获得最终的计算Bitmap内存公式
最终公式:总内存=(原始宽×缩放比)×(原始高×缩放比)×色彩空间
原图:1000宽X447高,位于drawable-xxhdpi(480dpi=3160dpi)文件包,设备Pixel-XL(560dpi=3.5160dpi)。主动设置inSampleSize=2。使用默认Bitmap.Config=ARGB_8888
内存占用=(原始宽×缩放比)×(原始高×缩放比)×色彩空间 =1000×0.5833×447×0.5833×4 =583×260×4 =606320byte ≈0.578MB
最后上图验证:
计算结果完美匹配运行结果,这里说明为何故意省略小数点3位之后,这是对应native层代码的float小数点结果转int时的舍弃。
理解Bitmap的最终内存占用计算原理和内存占用各个参数,咱们对Bitmap的处理时就有具体的目标。好比常见的优化Bitmap加载过程,其实就是对Bitmap加载时的各个变量参数设置修改。 常见的Bitmap优化: