HarmonyOS 页面卡不卡别靠感觉:用 DevEco Testing 做一次性能体检【鸿蒙心迹】

👋 你好,欢迎来到我的博客!我是【菜鸟学鸿蒙】
我是一名在路上的移动端开发者,正从传统“小码农”转向鸿蒙原生开发的进阶之旅。为了把学习过的知识沉淀下来,也为了和更多同路人互相启发,我决定把探索 HarmonyOS 的过程都记录在这里。
🛠️ 主要方向:ArkTS 语言基础、HarmonyOS 原生应用(Stage 模型、UIAbility/ServiceAbility)、分布式能力与软总线、元服务/卡片、应用签名与上架、性能与内存优化、项目实战,以及 Android → 鸿蒙的迁移踩坑与复盘。
🧭 内容节奏:从基础到实战——小示例拆解框架认知、专项优化手记、实战项目拆包、面试题思考与复盘,让每篇都有可落地的代码与方法论。
💡 我相信:写作是把知识内化的过程,分享是让生态更繁荣的方式。
如果你也想拥抱鸿蒙、热爱成长,欢迎关注我,一起交流进步!🚀
前言
页面开发完成以后,经常会听到一句评价:“我手机上点起来挺流畅的。”
这句话可以说明页面至少能正常使用,却不能直接当成性能结论。同一个页面,在不同设备、不同操作路径、不同数据量下,点击响应、页面完成显示和转场过程可能是三件不同的事。真正要判断一个页面是不是“卡”,更合适的方式是把主观感受拆成可以测量的指标。
华为官方提供的 DevEco Testing 就适合做这件事。其性能基础质量测试可以模拟用户操作,对应用启动、应用内滑动、点击以及资源占用等场景进行性能评估,涉及点击时延、帧率、内存、CPU 负载等指标,并提供过程截图及底层性能采集日志。
这次不做复杂业务,把场景缩小到一个最容易复现的问题:从列表页点击进入详情页,检查页面转场的响应时延、完成时延和卡顿表现,再根据报告决定下一步应该查哪里。
一、“我手机上很流畅”为什么不是性能结论
人的主观感受很容易受测试方式影响。
例如点击一个商品卡片进入详情页:
- 按钮很快出现按压反馈,不代表新页面已经完成显示;
- 新页面很快出现第一帧,不代表后续转场过程没有掉帧;
- 一台高性能设备表现正常,也不能说明其他目标设备上不存在问题;
- 只测试一次顺畅路径,也不能代表核心页面的整体性能。
官方的性能体验规则本身也是按具体指标区分的。
当前华为官方“时延”规则中,应用或元服务内点击操作响应时延应 ≤100ms;对于应用,应用内点击操作完成时延应 ≤900ms。这两个指标本来就不是一回事。
可以先这样理解:
| 指标 | 主要回答的问题 |
|---|---|
| 点击响应时延 | 用户点下去以后,界面多久开始作出可见响应 |
| 点击完成时延 | 从操作开始,到目标页面完成关键显示需要多久 |
| 转场卡顿率 | 页面切换动画过程中是否存在明显掉帧、停顿 |
| 滑动响应时延 | 手指开始滑动以后,页面多久开始跟随 |
| 滑动卡顿率 | 页面滚动过程中是否持续出现掉帧 |
因此,当一个页面被评价为“有点慢”时,第一步最好不要直接猜是网络、布局还是 ArkTS 代码,而是先确认到底慢在“响应”“完成”还是“动画过程”。
二、先把 DevEco Testing 能测什么弄清楚
DevEco Testing 当前提供性能基础质量测试和场景化性能测试。
性能基础质量测试偏向直接对应用进行标准化性能检查;场景化性能测试则允许通过脚本定义业务操作流,对实际使用场景进行性能评估,并提供步骤级操作视频以及 Perfdata 性能日志。
对于本文这种“进入页面到底慢不慢”的问题,先从基础质量测试入手就够了。
测试对象可以归纳成三类:
页面点击。
例如首页点击卡片进入详情页,重点看点击响应时延和点击完成时延。
页面转场。
例如 Navigation 页面切换,除了时延,还要看切换动画期间的卡顿表现。
页面滑动。
例如 List、Grid、WaterFlow 等内容区域滚动,可以继续看滑动响应和卡顿。
如果后续需要更精确地固定业务流程,再考虑场景化性能测试,不必一开始就把测试脚本做得很复杂。
三、准备一个最小测试应用
为了避免网络、数据库、图片下载等因素干扰,本例只准备两个页面:
Home
└── 点击“打开详情页”
↓
Detail
├── 标题
├── 若干文本内容
└── 可滚动列表
测试目标也保持简单:
- 测试 Home → Detail 的页面转场;
- 观察点击响应时延;
- 观察点击完成时延;
- 观察转场卡顿;
- 在 Detail 中滑动列表,再观察滑动性能。
页面路由采用官方目前推荐的 Navigation + NavPathStack 方式。
官方文档说明,从 API version 10 开始,更推荐使用 NavPathStack 实现 Navigation 页面路由;NavPathStack 用于管理 Navigation 的路由栈,可以完成页面跳转、返回、替换、删除等操作。
这里不需要为了性能测试专门接入某个应用侧“性能 SDK”。测试对象就是正常运行的 HarmonyOS 页面。
四、用 Navigation 搭一个可测试页面
这段代码只解决一个问题:构造一个清晰、稳定、容易重复操作的页面跳转场景。
@Entry
@Component
struct Index {
private pageStack: NavPathStack = new NavPathStack();
@Builder
pageMap(name: string) {
if (name === 'DetailPage') {
DetailPage();
}
}
build() {
Navigation(this.pageStack) {
Column({ space: 24 }) {
Text('Performance Test Home')
.fontSize(28)
.fontWeight(FontWeight.Bold)
Text('点击按钮进入详情页,用于观察页面转场性能。')
.fontSize(16)
Button('打开详情页')
.onClick(() => {
this.pageStack.pushPathByName('DetailPage', undefined);
})
}
.width('100%')
.height('100%')
.padding(24)
.justifyContent(FlexAlign.Center)
}
.title('Home')
.mode(NavigationMode.Stack)
.navDestination(this.pageMap)
}
}
@Component
struct DetailPage {
build() {
NavDestination() {
Column({ space: 16 }) {
Text('Detail Page')
.fontSize(28)
.fontWeight(FontWeight.Bold)
Text('下面放一些可滚动内容,用于继续观察页面滑动表现。')
.fontSize(16)
List({ space: 12 }) {
ForEach(
Array.from({ length: 40 }, (_, index) => index),
(item: number) => {
ListItem() {
Text(`Item ${item + 1}`)
.fontSize(18)
.width('100%')
.padding(16)
.backgroundColor('#F2F3F5')
.borderRadius(12)
}
}
)
}
.layoutWeight(1)
.width('100%')
}
.width('100%')
.height('100%')
.padding(24)
}
.title('Detail')
}
}
这里真正需要关注的不是页面样式,而是三件事。
第一,Navigation 持有一个明确的 NavPathStack。
第二,通过 pushPathByName() 触发从 Home 到 NavDestination 的页面切换。官方 Navigation 路由文档明确给出了基于 NavPathStack 进行页面管理和跳转的方式。
第三,详情页中保留一个 List,这样一次测试既能覆盖页面转场,也能继续观察滑动表现。
这个示例没有加入网络请求、图片解码或者数据库读取,是有意为之。性能排查最好先建立一个可重复的基线,再逐步增加真实业务因素。
五、配置性能测试时,页面遍历到底在做什么
准备好待测应用以后,可以在 DevEco Testing 中创建性能测试任务,并选择已经安装到测试设备上的应用。
官方对性能基础质量测试的定义就是“模拟用户操作”,覆盖启动、应用内滑动、点击等场景。
因此,页面遍历不是漫无目的地把整个应用点一遍。
对于本文的测试场景,更合理的遍历路线是:
启动应用
↓
Home
↓ 点击“打开详情页”
Detail
↓
向上滑动列表
↓
返回 Home
如果应用里还有搜索页、订单页、设置页,可以分别建立测试路径。不要为了“覆盖率”在一次性能任务里塞进大量互不相关的操作,否则最终看到某个异常指标时,很难快速对应到具体业务动作。
性能测试真正需要的是稳定、明确、可以重复的业务路径。
六、响应时延:用户点完以后,页面什么时候开始回应
这是最容易被“感觉挺快”掩盖的指标。
官方当前性能体验规则给出的点击操作响应要求为:
应用或元服务内点击操作响应时延应 ≤100ms。
这里不要把响应时延理解成“详情页完全加载完”。
它关注的是操作发生以后,界面多久开始产生响应。
例如点击“打开详情页”以后:
用户点击
│
├── 页面开始发生可见变化 ← 响应
│
├── 页面继续构建 / 渲染
│
└── 目标页面完成显示 ← 完成
这两个时间点不同,因此才需要同时观察响应时延和完成时延。
如果响应时延异常,排查重点应该靠近操作发生后的前半段,而不是看到“页面慢”就直接去优化整个详情页。
七、完成时延:页面动了,不代表页面已经准备好
官方当前规则中,应用内点击操作完成时延应 ≤900ms。
这个指标比响应时延更容易受到业务页面复杂度影响。
假设 Detail 页面后来加入这些逻辑:
点击商品
↓
创建目标页面
↓
读取本地缓存
↓
构建复杂组件树
↓
处理图片
↓
更新状态
↓
页面完成显示
用户点击以后可能马上看到转场,所以主观上觉得“已经响应了”;但如果目标页面迟迟没有进入稳定可用状态,完成时延仍然可能出现问题。
因此:
响应快 + 完成慢
和
响应本身就慢
是两种不同的问题。
这也是性能数据比“感觉卡”更有价值的地方。
八、完成时延正常,也要继续看卡顿
还有一种常见情况:
页面进入速度并不慢,但动画过程中有明显顿挫。
这时只看完成时延就不够了。
官方 AppAnalyzer 对 DevEco Testing 报告的诊断能力明确包含页面间转场的:
- 点击响应时延;
- 点击完成时延;
- 转场卡顿率。
对于页面滑动,还可以分析滑动响应时延和滑动卡顿率。
因此性能判断最好至少形成下面这个组合:
响应时延
+
完成时延
+
转场/滑动卡顿
而不是只拿一个数字判断页面好坏。
华为官方 SmartPerf 场景化采集资料也将页面切换的 ResponseTime、CompleteTime、HitchTimeRate 分开记录,并说明页面切换卡顿率与切换动效期间累计丢帧时间有关。
九、怎么阅读测试报告
跑完测试以后,不建议先盯着“通过/不通过”几个字。
更有效的阅读方式是从操作场景往回找。
例如发现:
Home → Detail
点击完成时延异常
先确认异常发生在哪一次操作,再观察当时的截图、日志和性能数据。
如果后续需要进一步定位,DevEco Testing 的性能报告还可以导入 DevEco Studio 的 AppAnalyzer。
官方文档说明,从 DevEco Studio 6.0.0 Beta3 开始,支持将 DevEco Testing 产生的性能检测报告导入 AppAnalyzer;AppAnalyzer 可以针对其中支持的指标继续诊断,并提供调优文件、时间戳、分析文档以及优化建议。
当前流程可以理解成:
DevEco Testing
│
│ 发现“哪一个业务场景表现异常”
▼
性能测试报告
│
│ 导出报告
▼
AppAnalyzer
│
│ 继续进行问题诊断
▼
Profiler / trace / 调用栈
│
▼
定位具体耗时位置
这里比较容易出现一个理解偏差:
DevEco Testing 和 AppAnalyzer 不是同一个测试入口。
官方也明确提示,两者在检测能力、检测方法以及场景识别方面存在差异,因此直接使用 AppAnalyzer 检测,与导入 DevEco Testing 报告进行诊断,结果可能不完全一致。
不要拿两套不同测试流程的结果做机械的一一对比。
十、根据数据决定下一步优化什么
拿到数据以后,比“马上改代码”更重要的是先判断问题属于哪一类。
响应时延高
重点检查点击操作之后、界面开始反馈之前发生了什么。
例如是否把过多同步工作放在用户操作后的关键路径上。
先定位,再调整,不要凭报告里的一个数字直接删除业务逻辑。
响应正常,完成时延高
说明用户操作以后已经较快得到反馈,但目标内容达到完成状态所需时间仍然偏长。
这时更应该关注:
- 目标页面构建过程;
- 页面初始化阶段执行的任务;
- 数据处理;
- 组件树复杂度;
- 资源准备过程。
具体是哪一个环节,需要结合 Profiler 或 trace 再确认。
时延正常,但转场卡顿
这时问题重点就从“多久完成”转向“完成过程是不是平滑”。
应该继续查看转场期间的渲染和帧表现。
页面切换正常,但列表滑动卡顿
不要继续围着 Navigation 查。
测试场景已经变化到页面滑动,应单独观察滑动响应、滑动卡顿,并检查对应滚动区域的构建和更新行为。
这也是做性能测试时很重要的一条原则:指标对应场景,场景对应代码路径。
十一、几个容易理解错的地方
1. 不要把响应时延和完成时延当成同一个指标
两者对应的是不同阶段。
只看其中一个,都可能漏掉真正的问题。
2. 不要自己编一个“流畅阈值”
对于本文涉及的点击操作,直接使用官方性能体验规则提供的标准更可靠。
当前官方给出的应用内点击操作规则是:
响应时延 ≤ 100ms
应用点击完成时延 ≤ 900ms
规则变化时,应以当前官方文档为准。
3. 测试路径不要太复杂
一次把登录、搜索、详情、支付、设置全部串起来,报告确实会更多,但异常与具体业务动作之间的关系反而更难确认。
核心页面拆开测通常更容易定位。
4. 不要因为“自己设备没卡”就跳过测试
性能标准针对的是具体指标,而不是开发者主观判断。
开发机上的一次顺畅操作只能算观察结果,不是性能数据。
5. DevEco Testing 找问题,Profiler 更适合继续找原因
DevEco Testing 可以帮助确认哪个业务场景、哪个性能指标出现异常;当问题需要深入到调用栈、trace 或具体时间段时,再进入 AppAnalyzer、Profiler 继续分析。
工具之间最好形成递进关系,而不是互相替代。
十二、实际项目可以按这个顺序排查
面对“这个页面感觉有点卡”,可以按下面的顺序处理:
1. 固定测试设备和应用版本
↓
2. 固定业务操作路径
↓
3. 用 DevEco Testing 执行性能测试
↓
4. 区分响应时延 / 完成时延 / 卡顿
↓
5. 找到发生问题的具体页面操作
↓
6. 导出性能报告
↓
7. 必要时导入 AppAnalyzer
↓
8. 使用 Profiler / trace 深入定位
↓
9. 修改代码
↓
10. 使用相同路径重新测试
最重要的是最后一步。
如果优化前后测试条件、页面路径和数据状态完全不同,那么两个数字本身就很难比较。
所以性能优化不是“看一次报告然后改代码”,而应该形成:
发现问题 → 定位问题 → 修改 → 同场景复测
这样一个闭环。
开发经验总结
DevEco Testing 的价值,并不是给页面简单贴一个“流畅”或者“不流畅”的标签,而是帮助我们把“感觉有点卡”拆成能够继续分析的问题。
这次最值得保留的几个思路是:
- 页面性能不要只凭开发者自己的设备体验判断;
- 点击响应时延和点击完成时延是两个不同阶段的指标;
- 页面完成速度正常,并不意味着转场过程不存在卡顿;
- 一次性能测试最好对应一条清楚、可重复的业务路径;
- DevEco Testing 更适合先发现场景问题,必要时再结合 AppAnalyzer、Profiler 和 trace 继续定位;
- 优化完成后,应使用相同业务路径重新测试,而不是换一个场景验证。
如果一个页面现在只是“感觉不太顺”,不妨先别急着重构。把一次点击拆成响应、完成和转场三个阶段,通常比直接猜是哪段代码慢,更容易找到真正值得优化的位置。
📝 写在最后
如果你觉得这篇文章对你有帮助,或者有任何想法、建议,欢迎在评论区留言交流!你的每一个点赞 👍、收藏 ⭐、关注 ❤️,都是我持续更新的最大动力!
我是一个在代码世界里不断摸索的小码农,愿我们都能在成长的路上越走越远,越学越强!
感谢你的阅读,我们下篇文章再见~👋
✍️ 作者:菜鸟不学编程
🧵 本文原创,转载请注明出处。
更多推荐



所有评论(0)