鸿蒙点击响应优化全攻略
摘要: 本文介绍了鸿蒙应用开发中的点击响应性能优化方法,重点分析了使用DevEco Studio工具(如AppAnalyzer、Profiler Frame和ArkUI Inspector)检测和优化响应时延的技术方案。通过分解响应阶段(输入、应用、渲染),定位性能瓶颈,并提出UI优化策略(减少嵌套层级、条件渲染、renderGroup缓存、LazyForEach懒加载和动态import),以实现
📑往期推文全新看点(文中附带最新·鸿蒙全栈学习笔记)
✒️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?
✒️ 嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~
✒️ 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?
✒️ 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?
✒️ 记录一场鸿蒙开发岗位面试经历~
✒️ 持续更新中……
响应优化概述
响应(Response)是指用户通过直接操作或间接触发请求后,应用程序执行运算处理请求,并更新界面状态的交互机制。
《应用性能体验建议》指出,应用或元服务内点击操作响应时延应<=100ms。为了保障应用操作响应及时,看护用户极致流畅体验,开发者需要分析从手势抬手到渲染上屏这段时间应用做了哪些耗时的操作,进而针对性地优化相关逻辑。
图1点击响应起止点示意图

点击响应优化就是指通过分析响应阶段、优化应用性能、加快点击后页面的响应速度,使用户可以得到流畅的操作体验。开发者优化自己应用的点击响应速度,既满足产品功能的高性能要求,增强产品同质化竞争中的优势,又能不断提升用户满意度。
分析工具
影响点击响应性能的因素有很多,借助DevEco Studio集成的相关分析工具,可以收集大量的系统数据,自动执行重复任务,建立统一的优化标准和流程,减少个人差异和误操作的可能性,帮助开发人员更好地了解性能瓶颈和优化潜力。在分析优化的过程中,可能用到以下工具中的一个或多个。
AppAnalyzer
AppAnalyzer是DevEco Studio中提供的检测评分工具,用于测试并评价HarmonyOS应用或元服务的质量,能快速提供评估结果和改进建议。当前AppAnalyzer支持的测试类型包括兼容性、性能、UX测试和最佳实践等。其中点击操作响应是性能类型中的一项检测规则,开发者可以使用该工具检测响应性能。
使用AppAnalyzer检测点击响应
- 启动DevEco Studio,连接设备,打开应用,然后依次执行以下操作。
- 单击菜单栏Tools > AppAnalyzer。
- 在AppAnalyzer页面Module选择框选择应用/服务工程模块。
- 根据应用的类别选择Category。
- 选择Rules,可以先点击Custom,再勾选”Quick Response To In-app Clicks”,即勾选”应用内点击操作响应快”评测规则。

- 点击Start启动检测,检测过程中,手机需要保持解锁亮屏状态。
- 获得检测结果。例如下图结果,表示点击响应性能检测失败,说明评测应用达不到100ms响应标准,存在进一步优化的空间。

Profiler Frame
DevEco Profiler 是DevEco Studio提供的场景化调优工具,其中Frame可以帮助开发者深度分析性能问题,通过录制应用运行过程中的关键数据,从而识别卡顿丢帧、耗时长等问题的原因所在。
使用Frame分析响应性能
- 抓取操作trace:启动DevEco Studio,连接设备,打开应用,然后依次执行以下操作。
- 启动Profiler。
- 选择应用、包名、进程。
- 选择Frame工具。
- 操作到指定页面,点击Create Session 创建一个Frame 模板。
- 点击Frame模板框中的播放按钮开始录制,操作应用界面点击响应,完成操作之后点击结束录制。

- 确认响应起点和终点:
- 根据点击响应的初始位置,找到手势抬起的那一帧,设置为分析起点,对应mmi-service泳道中H:service report的type为up的事件。
- 找到页面变化后的第一帧,设定为分析的终点,对应RSHardwareThread泳道的CommitAndReleaseLayers结束点。
- 分解时间段:点击响应的整体时延拆解后,主要分为三个阶段:输入阶段,应用阶段,渲染阶段。
| 首帧响应时延 | 起点 | 终点 | 基线(ms) |
|---|---|---|---|
| 输入阶段 | mmi_service对应的service report(type为up) | 应用DispatchTouchEvent的起点(type=1) | 8 |
| 应用阶段 | 应用DispatchTouchEvent的起点(type=1) | 页面首次发生变化帧对应的H:FlushMessage结束点 | 25 |
| 渲染阶段 | 对应的RS帧ProcessCommandUni起点 | 对应的RSHardwareThread::CommitAndReleaseLayers的结束点 | 20 |
其中,应用阶段(如下图中标记2与3之间的部分)是开发者需要关注优化的部分,一般来说,应用阶段耗时若超过25ms的基线,加上机器硬件的30ms左右耗时,整体的时延就可能超过100ms的标准,导致点击响应体验不佳,需要进一步定位性能问题。

- 分析定位原因:针对框选的应用阶段,分析主进程泳道,观察是否有耗时长的函数阻塞主线程;是否有超长耗时单帧。如果有长段的ExecuteJs 可以查看具体的调用栈或火焰图,定位耗时函数;如果是FlushLayoutTask阶段耗时,就需要结合UI组件树去分析,布局是否合理,是否有优化空间。

ArkUI Inspector
ArkUI Inspector是DevEco Studio中提供用于检查UI的工具,开发者可以借助它预览真机或模拟器中的UI效果,快速定位布局层级问题,也可以观察组件属性、不同组件之间的关系等。
常见问题根因分析
UI优化
应用开发中的用户界面UI(User Interface)是用户与应用程序交互的关键部分。使用不同类型的布局,能在界面显示上达到预期效果。某些方式能将页面排布得更加美观,但也容易引入不合理的结构问题。如果UI界面中存在过度的布局计算、冗余的元素绘制,将会带来设备资源的大量开销,造成响应性能的衰退。
减少嵌套层级
布局的嵌套层次过深会导致在创建节点及进行布局时耗费更多时间。因此开发者在开发时,应避免冗余的嵌套,并尽量使用扁平化布局来优化嵌套层级。
减少渲染时间
if/else条件渲染是ArkUI应用开发框架提供的渲染控制能力,可根据应用的不同状态,渲染对应分支下的UI描述。
用renderGroup缓存动效
页面响应时,可能大量使用属性动画和转场动画,当复杂度达到一定程度之后,就有可能出现卡顿的情况。renderGroup是组件通用方法,它代表了渲染绘制的一个组合。
具体原理是在首次绘制组件时,若组件被标记为启用renderGroup状态,将对组件及其子组件进行离屏绘制,将绘制结果合并保存到缓存中。此后当需要重新绘制相同组件时,就会优先使用缓存而不必重新绘制了,从而降低绘制负载,进而加快响应速度。
图2renderGroup使用场景示例

为了能使renderGroup功能生效,有以下限制条件:
- 组件内容固定不变:组件及其子组件各属性保持固定,不发生变化。如果组件内容不是固定的,也就是说其子组件中存在某些属性变化或者样式变化,此时如果使用renderGroup,那么缓存的利用率将大大下降,并且有可能需要不断执行缓存更新逻辑,在这种情况下,不仅不能优化卡顿效果,甚至还可能使卡顿恶化。例如:文本内容使用双向绑定的动态数据;图片资源使用gif格式;使用video组件播放视频。
- 子组件无动效:由组件统一应用动效,其子组件均无动效。如果子组件上也应用动效,那么子组件相对父组件就不再是静止的,每一帧都有可能需要更新缓存,更新逻辑同样需要消耗系统资源。
LazyForEach懒加载
使用LazyForEach懒加载替换ForEach,避免像ForEach那样一次性初始化和加载所有元素,从而使首帧绘制时创建列表元素时间大大减少,提升响应性能表现。
动态import
动态import是一种模块加载机制,允许应用程序在运行时按照实际需求去加载相关模块。在某些条件满足时(比如用户交互时,或ABTest分支切换时)再加载特定模块,可以减少初始化import的加载时间和资源消耗,这将有助于提高应用程序的内存性能和响应速度。
与静态import不同,动态import仅在需要时才消耗CPU等资源;相比静态import在编译时就确定了引入的所有模块,动态import还有更佳的语法灵活性,借助这种灵活,能够实现代码和路由级别的粒度分割,优化模块层次的懒加载性能。
并发优化
并发是指多个任务在同一个时间段内同时触发执行,具体逻辑中使用多线程异步执行,与之相对的概念是串行任务,按顺序同步执行。
应用中的并发优化就是在响应用户操作期间,尽可能地让主线程只执行UI绘制相关的任务,而将非UI的耗时任务分配给其他线程或者延迟处理。这样借助多线程的异步技术,充分利用多核处理器的能力,提高应用程序的并发处理能力,减少用户等待时间,保证用户界面的响应流畅性。
异步任务并发处理
使用多线程并发能力进行开发的过程中,主要实现方式有:
- 利用TaskPool执行简单并行任务:将一些耗时的操作放入异步任务中处理,避免阻塞主线程,提升应用的响应速度;
- 利用Worker完成周期类耗时操作:Worker可以空跑在后台等待事件触发,周期触发耗时操作使用Worker,这样可以避免TaskPool频繁拉起影响性能。
使用组件异步加载特性
Image组件支持异步加载特性:当应用在页面上展示一批图片的时候,会先显示空白占位块,当图片在其他线程加载完毕后,再替换占位块。这样图片加载就可以不阻塞页面的显示,给用户带来良好的交互体验。
设置示例:
// syncLoad设置false,或缺省设置,都是异步加载图片
Image('https://example.com/icon.png')
.syncLoad(false)
相应的,如果展示图片数目很少,或加载本地图片,耗时明显较少时,这时建议配置syncLoad属性为true,使图片同步加载,避免特定情况下图片加载出现的闪烁。
代码逻辑优化
代码逻辑的优劣对应用响应速度的影响是比较明显的,特别是点击切换后新页面中的aboutToAppear、onPageShow等生命周期回调,以及点击操作页面中的aboutToDisappear等,需要充分优化代码、减少冗余、避免耗时,提升执行效率。
基于平台SDK的开发框架下,对App生命周期的理解,可以帮助开发人员识别程序在不同阶段的行为,弄清楚不同形态转换时触发的接口性质、各函数被调用的频率,进而挖掘出代码优化的方向。
下图是页面及自定义组件的生命周期流程:
图3生命周期流程图

通常可以采用的逻辑优化方法有:
- 选择合适的数据结构
索引存取考虑使用array数组,hash查找考虑使用map,去重逻辑考虑使用set等;
有时开发者使用object变量作为容器去处理map的逻辑,可以考虑使用ArkTS提供的高性能容器类,直接使用HashMap;
遇到纯数值计算的场合,推荐使用TypedArray的数据结构,比如Int8Array、Int32Array、Float32Array、BigInt64Array等。
- 合理使用缓存
当某些运算结果会反复使用时,以空间换时间,提前缓存以便于下次调用。
- 注意对象new和delete的频率
new和delete可能会触发内存管理回收,占用CPU资源从而影响界面渲染的能力,需要根据情况调整其频次。尤其在循环代码中,频繁的new、delete更会带来恶化的性能表现,应该尽量将new/delete优化到循环外去处理。
- 延迟执行资源释放操作
将资源关闭和释放操作放在setTimeout函数中执行,使其延迟到系统相对空闲的时刻进行,可以避免在程序忙碌时段占用关键资源,提升整体性能及响应能力。
- 减小拖动识别距离
应用识别拖动手势事件时需要设置合理的拖动距离,设置不合理的拖动距离会导致滑动不跟手、响应时延慢等问题。针对此类问题可以通过设置distance大小来解决。
视觉感知优化
上述几节内容,是从减少时延绝对值的角度来提升响应体验,而视觉感知优化则是通过交互设计的优化,提升用户响应速度的感知。
从响应速度的反面角度来讲,应用的卡顿其实就是视觉上出现了不流畅的画面,引起了用户的注意,令其产生了一定的不适感。这也就意味着,在用户操作后,需要第一时间从视觉层面给与反馈响应,从而解决视觉动作带来的不适。
开发者可以在用户的交互动作开始时,从感知角度添加一些动画元素,比如单击效果、转场缩放、加载进度条、共享动画等,这些可以告诉用户目前状态发生了变化,APP在快速地运作着;而动画的背后是:数据的计算,布局的渲染,内容的加载等等,当新界面渲染显示完成,上述动画元素就可通过渐变消失、移出屏外等友好的方式退出视觉区域。
图4应用响应的两个视角

使用这样连贯的感知元素,能提供一种视觉隐喻,将用户的注意力从上个页面平滑地过渡到下个页面;交互动画表现得友好、有趣和实用,则用户在响应侧的体验会更加舒适,从主观上也会认为应用性能好、反应速度快。

更多推荐
所有评论(0)