一、过度绘制
当应用页面布局的嵌套程度过深时,应用渲染阶段会存在一些组件的绘制指令被其他组件的绘制指令部分或完全覆盖遮挡的情况,造成冗余的CPU、GPU等计算资源的使用。
定义:一个屏幕上的像素点被重复绘制了多次的情况,被称为过度绘制。
过度绘制的危害
| 危害 | 说明 |
|---|---|
| CPU/GPU资源浪费 | 重复绘制消耗计算资源 |
| 渲染性能下降 | 影响页面流畅度 |
| 耗电量增加 | 不必要的计算消耗电能 |
二、使用方式
2.1 使用前提
前提条件:需在系统设置中开启开发者模式。
2.2 shell命令
系统提供的过度绘制调试功能,可通过shell进行开启或者关闭。
| 操作 | 命令 |
|---|---|
| 开启 | param set debug.graphic.overdraw true |
| 关闭 | param set debug.graphic.overdraw false |
| 查看状态 | param get debug.graphic.overdraw |
2.3 命令示例
# 开启过度绘制调试 param set debug.graphic.overdraw true # 关闭过度绘制调试 param set debug.graphic.overdraw false # 查看是否开启(true表示开启,false表示未开启) param get debug.graphic.overdraw三、过度绘制颜色对应关系
开启了过度绘制调试功能后,打开应用界面,存在过度绘制情况的像素会被代表着不同级别的颜色方框高亮出来。
| 颜色 | 过度绘制次数 | 严重程度 |
|---|---|---|
| 原色 | 无过度绘制 | 正常 |
| 蓝紫色 | 1次 | 轻度 |
| 绿色 | 2次 | 中度 |
| 浅红色 | 3次 | 重度 |
| 深红色 | 4次或更多 | 严重 |
规律:颜色越深,代表过度绘制情况越严重。
四、过度绘制组件分析
4.1 问题示例代码
以下是一个存在冗余的背景颜色嵌套问题的示例应用程序:
@Entry @Component struct Index { @State message: string = 'Hello World' build() { Row() { Column() { Column() { Column() { Column() { Column() { Text("Hello World") } .width('80%') .height('80%') .backgroundColor(Color.White) } .width('80%') .height('80%') .backgroundColor(Color.White) } .width('80%') .height('80%') .backgroundColor(Color.White) } .width('80%') .height('80%') .backgroundColor(Color.White) } .width('80%') } .height('80%') } }4.2 分析结果
开启过度绘制调试功能后,应用界面显示情况如下:
| 组件层级 | 颜色 | 过度绘制次数 |
|---|---|---|
| Text(最内层) | 深红色 | 4次或更多 |
| 内层Column | 浅红色 | 3次 |
| 中层Column | 绿色 | 2次 |
| 外层Column | 蓝紫色 | 1次 |
| 最外层Column | 原色 | 0次 |
规律:从Hello World文字组件开始,由内到外的Column组件分别显示为深红色 → 浅红色 → 绿色 → 蓝紫色 → 原色。
说明:随着嵌套程度的加深,每一个Column组件的背景颜色绘制都会带来一次过度绘制。
4.3 注意事项
状态栏、侧边栏等系统界面也会在过度绘制调试功能中被统计到,此为正常现象,不属于应用需要优化的范围。
五、优化方法
| 方法 | 说明 |
|---|---|
| 显隐控制/条件判断 | 通过显隐控制或者if-else条件,减少页面上冗余的组件 |
| 减少被遮挡组件的绘制 | 减少被完全遮挡的组件上的绘制指令,如背景颜色、组件内容等 |
| 采用扁平化布局 | 减少组件嵌套深度,将大小相近、功能类似的布局组件合并为一个组件 |
优化示例
// 优化前:多层嵌套 + 重复背景色 Column() { Column() { Column() { Text("Hello World") } .backgroundColor(Color.White) } .backgroundColor(Color.White) } .backgroundColor(Color.White) // 优化后:扁平化布局 Column() { Text("Hello World") } .backgroundColor(Color.White)