
HarmonyOS NEXT应用元服务布局优化精简节点数
建议开发者优先使用Code Linter扫描工具进行代码检查,重点关注@performance/hp-arkui-remove-container-without-property规则。若扫描结果中出现该规则相关问题,可参考本章节提供的优化建议进行调整。
布局阶段是采用递归遍历所有节点的方式进行组件位置和大小的计算, 如果嵌套层级过深,将带来了更多的中间节点,在布局测算阶段下,额外的节点数将导致更多的计算过程,造成性能劣化。我们通过模拟了10、100、500、1000层Row嵌套的情况下,通过Profiler工具抓取Launch数据查看对应的首帧绘制,以及页面Measure/Layout时间进行对比。
Row() {
... // 10、100、500、1000层Row容器嵌套
Row() {
Text('Inner Text')
}
然后进一步对比了在平铺的情况下,Row内组件个数在10、100、500、1000的条件下,使用Profiler工具抓取Launch的数据情况,得到如下结果如表1所示。
undefin Row() {
Row() {}
... // 10、100、500、1000层Row容器并排
Text('Inner Text')
} ed
说明
以上数据来源均为版本DevEco Studio 4.0.3.415、SDK 4.0.10.9条件下测试得到,不同设备类型数据可能存在差异,测试数据旨在体现性能优化趋势,仅供参考。
根据以上数据对比发现,组件平铺和嵌套在相同组件个数的情况下,其性能差异不大,并且整体上趋势保持一致,随着组件数量增加呈现线性增长的劣化,由此可以得到结论,真正影响布局性能的因素是参与布局的节点数量。所以在进行布局时,应该尽量减少整体的节点数,来减少布局的性能劣化。
针对减少总节点,主要有两个方向:
移除冗余的节点。
使用扁平化布局减少节点数。
移除冗余节点
对于常出现冗余的情况,例如可能会在Row容器包含一个同样也是Row容器的子级。这种嵌套实际是多余的,并且会给布局层次结构造成不必要的开销。
Row() {
Row(){
Image()
Text()
}
Image()
}
由于其中Row容器父子布局方向相同,所以可以去掉Image和Text外层的Row来减少层级,如果视图更加复杂,布局在渲染时,会产生没有必要的计算。
Row() {
Image()
Text()
Image()
}
共15个节点,并且其中并没有冗余的嵌套节点。而扁平化布局是一种让页面结构变浅变宽的方式,通过一些高级组件如RelativeContainer、Grid等容器,可以让元素在平面上展开。这种布局方式能够有效减少由于使用线性布局带来的嵌套深度,将其用于描述布局的容器节点进行优化,达到精简节点数的目的。图一中将线性布局改成相对布局的情况下,嵌套2层、总共10个节点,相比之下前后少了5个节点。尽管在这里只是多了一层,但是实际开发中的布局往往非常复杂,冗余带来的开销可能非常影响布局性能,尤其是在列表中动态创建组件时,带来的性能影响是显著的。
使用扁平化布局减少节点数
在某些情况下,开发者所实现的布局在嵌套层级上是没有冗余的,但是嵌套层级仍然较深,可能无法通过调整现有的布局方案,使其不包含多余的布局,唯一的解决方案可能是,通过切换到完全不同的布局类型来实现层次结构的扁平化。
例如图1中元素结构示意图,传统使用线性布局的情况下,总共存在4层嵌套、
图1 扁平化布局示意图
这种方式对于布局的影响主要体现在:
页面创建时,扁平化减少了中间的嵌套层级,使总的组件节点的数量越少,在进行布局时所需要进行的计算相对越少。
页面更新时,当要更新的结构是嵌套子树的结构,其树内包含过多节点时,整体更新会导致更新的节点数过多,造成布局性能劣化。
所以当页面不存在冗余节点时,可以考虑是否能够通过替换为更高级的布局使得页面扁平化,来达到减少节点数的目的。主要方式可以参考:
RelativeContainer 通过相对布局实现扁平化。
绝对定位 通过锚点定位实现扁平化。
Grid 通过二维布局实现扁平化。
本文主要引用整理于鸿蒙官方文档
