type
status
date
slug
summary
tags
category
icon
Bitmap 是内存优化逃不了的一个东西,本文探讨下,Bitmap 中的 density 到底是什么东西,它是如何影响到内存的使用的
先看下 density 的文档注释
简单来说 density 是用来绘制缩放用的,默认情况下的 density 就是屏幕的 density(resources.displayMetrics.densityDpi),假如我修改了一张 Bitmap 的 density,那么图片的显示应该会发生缩放,写个简单的 demo 验证下
<!-- more -->
界面
notion image
输出:
从输出可以看出,Bitmap 的 density 只是会影响到显示而已,并不会影响到 Bitmap 本身的大小,所以这个属性不会影响到内存占用过多的问题
界面中可以看出,density 导致图像的缩小一倍和放大一倍
那么影响内存的是什么呢,我们知道把一张 xxhdpi 的图片放到 xhdpi 中是不行的,这样会导致图片扩大,这里的扩大是指图片本身内存占用的扩大,而不是显示上面的,跟踪下 BitmapFactory.decodeResource(resources, R.drawable.male_xhdpi) 的代码调用,跟踪到 decodeResourceStream() 函数的时候,发现了 density 的身影
发现 Options 里面有两个属性 (inDensityinTargetDensity),inTargetDensity 被赋值成了当前设备的像素密度,那么 inDensity 被赋值成啥了呢?代码中看是赋值成了参数 value 的 density,回溯函数看看 value.density 是哪里来的
TypeValue 的值只有在这里有写入现象,猜测是根据 resource 的等级来赋值的,比如 xhdpi 就是 320dpi,xxhdpi 就是 480dpi(这些数值可以在官网查看),写段代码测试下
输出
恩,看来这个推测很准确
既然知道了这两个数值是什么意义,那么继续跟踪代码,跟踪后发现最后调用的是一个 native 函数
androidXRef 看下这部分的代码
忽略了多余的代码,分析部分看中文注释
可以在代码中看到,Options 的 inDensityinTargetDensity 是用作 Bitmap 的缩放用的,此缩放并不是视觉上的缩放,而是缩放了 Bitmap 的真正尺寸,那么这里就需要注意内存上的消耗了,不要把 xxhdpi 的图片放到 xhdpi 下面
对于上面的 inScreenDensity,在 decodeResource 的流程里面并没有发现它的赋值过程,那么它肯定是初始值 0,查看了下注释,他表示当前 display 设备的 density,如果 inScreenDensity == density 就不会对图片进行缩放
总结下过程: 通过 resource 获取 Bitmap 的时候,先根据资源文件获得 inDensityinTargetDensity 就是当前设备的 density,图片解码后在通过 canvas 缩放 inTargetDensity / inDensity 个倍数,就获得了缩放尺寸后的 Bitmap
探索阻尼动画优雅的实现方式探索 Android RippleDrawable作为背景是如何绘制到View外的
Loading...