采集数据
台架设备硬件参数:
private fun display(){
// 获取 DisplayMetrics 实例
val displayMetrics = DisplayMetrics()
// windowManager.defaultDisplay.getMetrics(displayMetrics) // 屏幕尺寸,去除导航栏
windowManager.defaultDisplay.getRealMetrics(displayMetrics) // 屏幕真实尺寸
val displayMetrics1 = resources.displayMetrics
val widthPixels1 = displayMetrics1.widthPixels
val heightPixels1 = displayMetrics1.heightPixels
Log.i(TAG, "resources 屏幕宽度 (像素): $widthPixels1")
Log.i(TAG, "resources 屏幕高度 (像素): $heightPixels1")
Log.i(TAG, "------------------------------")
val defaultDisplay = windowManager.defaultDisplay
val width = defaultDisplay.width
val height = defaultDisplay.height
Log.i(TAG, "windowManager 屏幕宽度 (像素): $width")
Log.i(TAG, "windowManager 屏幕高度 (像素): $height")
Log.i(TAG, "------------------------------")
// 获取屏幕宽度和高度(像素)
val widthPixels = displayMetrics.widthPixels
val heightPixels = displayMetrics.heightPixels
// 获取屏幕宽度和高度(dp)
val widthDp = widthPixels / displayMetrics.density
val heightDp = heightPixels / displayMetrics.density
// 获取屏幕密度
val density = displayMetrics.density
val densityDpi = displayMetrics.densityDpi
// 打印屏幕尺寸和分辨率
Log.i(TAG, "getRealMetrics 屏幕宽度 (像素): $widthPixels")
Log.i(TAG, "getRealMetrics 屏幕高度 (像素): $heightPixels")
Log.i(TAG, "屏幕宽度 (dp): $widthDp")
Log.i(TAG, "屏幕高度 (dp): $heightDp")
Log.i(TAG, "density : $density")
Log.i(TAG, "densityDpi : $densityDpi")
}
- 屏幕宽度 (像素): 1920
- 屏幕高度 (像素): 1080
- density : 1.3312501
- densityDpi : 213
密度标识符和对应的密度值
| dpi目录 | 对应 DPI | 缩放值 |
|---|---|---|
| drawable-ldpi | 120 | 0.75 |
| drawable-mdpi | 160 | 1.0 |
| drawable-hdpi | 240 | 1.5 |
| drawable-xhdpi | 320 | 2.0 |
| drawable-xxhdpi | 480 | 3.0 |
| drawable-xxxhdpi | 640 | 4.0 |
图片内存的占用本质
图片占用空间的大小不是图片占用内存的大小,占用空间是在磁盘上占用的空间,内存大小是加载到内存中占用的内存大小。两个只是单位是一样的,本质不是一个概念。
- 8.0 之前版本为 Bitmap 像素从 Java heap 申请内存。其核心原理是Bitmap 的像素是保存在 Java 堆上。
- 8.0 版本为 Bitmap 像素从 Native heap 申请内存。其核心原理主要是通过 calloc 为 Bitmap 的像素分配内存,这个分配就在 Native 堆上
影响 Bitmap 占用内存的因素:
- 图片最终加载的分辨率;
- 图片的格式(PNG/JPEG/BMP/WebP);
- 图片所存放的drawable目录;
- 图片属性的色彩模式;
- 设备的屏幕密度
台架设备是固定的,1920*1080 ,density = 1.3 , dpi = 213 ;这组数据没有完全匹配的 drawable 目录,但是放在 drawable-hdpi ,DPI =240 的目录下更合适、更省内存。
内存占用=1920×1080×4=7,136,640 bytes≈7.9 MB
// drawable-hdpi
`hdpi`对应的密度为 240dpi,通常在`hdpi`目录下,图片会被缩放为设备密度的比例。
由于设备的实际 dpi 为 213(根据 density 计算),因此需要进行缩放
缩放比例=213/240≈0.8875
计算缩放后的图片尺寸:
新宽度=1920×0.8875≈1700 pixels
新高度=1080×0.8875≈958 pixels
内存占用=1700×958×4≈6,514,400 bytes≈6.2 MB
测试数据
在 Demo 应用中的数据
图片资源存放在 drawable、drawable-hdpi、drawable-xhdpi、drawable-xxhdpi 各个目录下,测试的 total、Java、native、code、other 占用的内存数据。
在应用中的数据
在 launcher 中不同的手顺,所对应的内存数据
优化后的数据
优化操作:
- 剔除一部分多余的依赖库
- widget 资源图转 Webp
- 图片资源存放在 drawable-hdpi 目录下
优化过程中,每次的内存快照图,都是在 5 分钟左右,更改变量再去测试下一次的内存占比。测试过程有其他事件打断,测试手顺没有保证绝对一致,数据可能存在一定的误差,但是总体来看,有所下降。内存优化空间在 50M~150M 左右。
待优化的点
- 第三方库重复加载
- 图片资源转 SVG
- Layout 布局文件
- SP 高频读写
- 按需 选择合适的解码方式,ARGB_8888 或 RGB_565
- 图片分辨率与实际显示 view(列帧动画方面采用的是
全尺寸(550*450)图片)