1.1布局流程
了解如何在布局方面进行性能优化之前先来看看ArkUI布局的过程吧。(如下图所示)
应用侧会根据前端UI描述创建后端的页面节点数(包含处理UI组件属性更新,布局测算,事件处理等逻辑)。例如上图中在 ArkUI 布局中,应用侧依前端 UI 描述创建后端页面节点树,含 UI 事件属性更新等逻辑。Index 中的 InfoView 组件生成 CustomNode(处理自定义组件业务),Row、Text 等组件生成 FrameNode(系统组件节点)。UI 线程对元素测算和布局,Measure 阶段确定组件测量宽高,Layout 阶段确定最终宽高和顶点位置,之后根据页面节点树生成渲染树(由 RenderNode 组成,描述元素布局信息),渲染线程据此绘制。布局阶段若视图嵌套层级深、节点多,Measure 和 Layout 中遍历测量耗时过长。
1.2 优化措施
1.2.1 精简节点数量:
随组件数量增加,性能呈现线性增长的劣化;且平铺和嵌套在相同组件个数时性能差异不大,且整体趋势保持一致。
方法:
- 减少总节点数:
- 移除冗余节点
- 使用扁平化布局减少节点数
1.2.2合理控制元素显示与隐藏
ArkUI中控制方式有:if条件渲染,visibility属性控制
if条件为true时,创建(measure)并布局(layout)元素;
visibility属性的值无论为visible还是none,都会创建元素,在值为visible时layout。
因此:
- 在对性能要求较高,并且会频繁地切换元素地显示与隐藏的情况下,应该避免使用if条件判断而改为visibility的属性控制
- 如果组件的创建非常消耗资源,且不会立即使用,也非频繁切换交互的情况下只在特定的条件下才会出现时,可以通过if条件渲染来进行内容的显示与隐藏控制,达到懒加载的效果。
1.2.3 给定组件的宽高
- 对于组件的宽高不需要自适应的情况下,当其组件外部的容器尺寸发生变化时,建议给定组件的宽高数据,减少进行measure阶段。
- 对于能够在初期给定宽高的组件,在进行UI描述时,尽量给定宽高的大小,能够减少由于容器尺寸变化造成的重新测算(measure)过程的性能消耗。
1.2.4 使用推荐的布局组件
该图基于相同的布局层数和节点数的情况下的测试结果
加载过程分析常用指标:
- 完全显示所用时间(Time To Full Display,TTFD):表示应用生成具有完整内容的第一帧所用的时间,包括在第一帧之后异步加载的内容。
- 丢帧率(Janky Frames):表示一个时间周期内的丢帧比率,是指一个时间周期内有问题的帧比例。HarmonyOS系统要求每一帧都要在11.1ms(90Hz刷新率)内绘制完成,如果页面有在11.1ms内完成这一帧的绘制,就会出现丢帧。部分丢帧一般用户肉眼是感知不到的,只有出现连续丢帧用户才有明显感知。
- 独占内存(Unique Set Size,USS):一个进程所占用的私有内存,即该进程独占的内存。它反映了运行一个特定进程真实的边际成本(增量成本)。
对列表渲染时间。页面滑动帧率,应用内存占用等方面带来优化,提升性能和用户体验的手段如下:
2.1 懒加载(lazyForEach()代替ForEach())
两者对比
ForEach:
- 如果列表数据较少,数据一次性全量加载不是性能瓶颈时,可以使用ForEach。ForEach会从列表数据源一次性加载全量数据。
- 渲染逻辑:
LazyForEach
- 其实现了按需加载,针对数据量大列表组件复杂的场景,解决了页面首次启动时一次性加载数据的时间消耗及占用过多资源的问题,减少了内存峰值,可提升页面响应速度。
- 渲染逻辑:
数据量小时,两者性能差异不大,LazyForEach()略好;数据量大时,LazyForEach性能好
总结
- 使用LazyForEach懒加载这项技术后,相比ForEach这种加载方式,在列表数据量较小(100条内)且数据一次性全量加载不是性能瓶颈时,两者各项性能指标差异不大。但当列表数据较长特别是达到10000条数据量后,ForEach的性能指标会有“指数级别”的显著劣化,滑动会出现明显的卡顿,甚至会出现应用crash等现象;而LazyForEach因为采用了懒加载技术能明显减少首屏完全显示所用时间,降低应用的独占内存,提高页面滑动帧率,带来更好的性能。
- 在使用LazyForEach时,合理添加缓存列表项,能带来列表滑动帧率的提升,减少“滑动白块”的出现。
使用组件复用这项技术后,因省去了组件频繁创建这一耗时操作,故能明显减少“有规律、且重复”的丢帧现象,提高列表页面的加载速度和响应速度,丢帧率会降低。 - 对页面进行布局优化在大数据量下能对页面性能产生一定的优化。
2.2 缓存列表项
LazyForEach懒加载可以通过设置cachedCount来指定缓存数量,在设置cachedCount后,除屏幕内显示的Listltem组件外,还会预先将屏幕可视区外指定数量的列表项数据缓存。这样当一个屏幕数据加载完成后,再次向下滑动时,会先加载上一次请求的数据,加载完成后,再加载本次请求的数据。
实现代码
- 不同cachedCount对列表滑动帧率的影响
一般而言,缓存的cachedCount=n/2(n为一屏显示的列表数)的时候,效果较好。在实际开发中也要根据实际场景合理去设置缓存数量:- 例如列表项中需要显示网络数据,而网络数据加载较慢,为了提升列表信息的浏览效率和浏览体验,我们可以适当的多设置一些缓存数量(cachedCount大于n/2);
- 如果列表中需要加载一些大图或者视频等,这些数据占用的内存较大,为了减少内存占用,我们需要适当减少缓存数量的设置(cachedCount小于n/2)
因此,在实际场景中,需要不断尝试验证,设置适当的缓存 数量,来达到体验和内存的平衡
2.3 组件复用
HarmonyOS应用框架提供了组件复用能力,可复用组件从组件树上移除时,会进入到一个回收缓存区。后续创建新组件节点时,会复用缓存区中的节点,节约组件重新创建的时间。尤其在列表等场景下,其自定义子组件具有相同的组件布局结构,列表更新时仅有状态变量等数据差异。通过组件复用可以提高列表页面的加载速度和响应速度。
每种组件都是key-value这样的形式
关键代码:
2.4 布局优化
列表不同于其他布局,包含了大量重复循环的Listltem,所以对每一个Listltem的布局优化格外重要。错误的布局方式可能会导致组件树和嵌套层数过多,在创建和布局绘制阶段产生较大的性能开销,导致界面卡顿。合理使用布局,减少嵌套层数,能提高布局效率。
- 布局过度嵌套会导致应用内存增加,且会影响应用的帧率导致丢帧增加,所以开发者在写列表这类循环组件的代码时,需要特别考虑对其布局进行优化。一般而言布局的最大嵌套层级控制在5-8层左右即可,过度的去优化布局会导致代码开发难度加大,代码不易于阅读理解,增加后续的维护成本,不利于多设备的适配,且也不会带来特别显著的性能提升。
在应用开发中,动画可以为用户界面增添生动、流畅的交互效果,提升用户对应用的好感度。然而,滥用动画也会导致应用性能下降,消耗过多的系统资源,甚至影响用户体验。为了提升应用性能和用户体验,可采取以下措施:
- 使用系统提供的动画接口:系统接口经过精心设计和优化,能够在不同设备上提供流畅的动画效果,最大程度地减少丢帧率和卡顿现象。
- 使用图形变换属性变化组件布局:通过对组件的图形变换属性进行调整,而不是直接修改组件的布局属性,可以减少不必要的布局计算和重绘操作,从而降低丢帧率,提升动画的流畅度和响应速度。
- 参数相同时使用同一个animateTo:当多个动画的参数相同时,合并它们并使用同一个animateTo方法进行处理能够有效减少不必要的计算和渲染开销。
- 多次animateTo时统一更新状态变量:在进行多次动画操作时,统一更新状态变量可以避免不必要的状态更新和重复渲染,从而减少性能开销。
- 使用renderGroup:在单一页面上存在大量应用动效的组件时,可以使用renderGroup方法来解决卡顿问题,从而提升动画性能。
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/hd-xnyh/78491.html