HarmonyOS ArkGraphics 2D NativeVSync 实操:请求下一帧并记录真实结果
这次实操的结果很明确:NativeVSync 创建、请求和帧率设置都返回 0,真机停止时累计收到 1,401 次回调。我们把每次回调只写入 Native 原子计数,再由 ArkUI 定时读取,做成一个可复用的帧节拍诊断页。
本次实验做什么
页面启动时执行 OH_NativeVSync_Create_ForAssociatedWindow()(无法取得窗口 SurfaceId 时回退到 OH_NativeVSync_Create())、OH_NativeVSync_SetExpectedFrameRateRange()、OH_NativeVSync_DVSyncSwitch() 和 OH_NativeVSync_RequestFrameWithMultiCallback()。页面不会在 VSync 回调线程直接操作 ArkUI,而是由定时器读取 Native 层的原子计数。
准备
- DevEco Studio,API 26 工程。
- HUAWEI Mate 60 Pro 真机。
- Native 文件:
entry/src/main/cpp/native_vsync.cpp。 - ArkTS 页面:
entry/src/main/ets/features/graphics2d/NativeVsyncPage.ets。
实施过程
1. 创建 VSync 对象并提交请求
const char name[] = "FilterLabVsync";
g.vsync = OH_NativeVSync_Create(name, strlen(name));
OH_NativeVSync_ExpectedRateRange range{30, 60, 60};
g.rateStatus.store(OH_NativeVSync_SetExpectedFrameRateRange(g.vsync, &range));
g.dvStatus.store(OH_NativeVSync_DVSyncSwitch(g.vsync, true));
g.requestStatus.store(OH_NativeVSync_RequestFrameWithMultiCallback(g.vsync, OnFrame, nullptr));
2. 在回调中只记录数据
void OnFrame(long long timestamp, void *) {
if (!g.running.load()) return;
g.callbacks.fetch_add(1);
g.last.store(timestamp);
long long period = 0;
if (OH_NativeVSync_GetPeriod(g.vsync, &period) == 0) {
g.period.store(period);
}
OH_NativeVSync_RequestFrameWithMultiCallback(g.vsync, OnFrame, nullptr);
}
回调线程只写原子变量,下一次回调仍由 NativeVSync 请求,不把 ArkUI 组件调用放进原生线程。
3. ArkTS 页面读取快照
const snapshot: NativeVsyncSnapshot = vsyncApi.snapshot();
this.callbacks = snapshot.callbacks;
this.periodNs = snapshot.periodNs;
真机结果与问题定位
API 26 真机首次进入页面时,ArkTS WindowProperties 没有暴露可用的 windowId,日志中的字段为空;Native 层随后创建临时 NativeImage 获取 NativeWindow,尝试查询 SurfaceId 并建立关联窗口 VSync。即使页面上的计数刷新存在时序差异,Native 释放日志仍记录到真实回调:第一次运行 4377 次,第二次 180 次,最新一次 1401 次。由此确认回调线程在工作,0 只是页面快照截取时没有赶上共享状态刷新。
因此本篇的证据以 Hilog 的累计回调数为准,不把某一张瞬时页面截图当成帧率结果;也不制作会掩盖时序问题的伪 GIF。将计数接入实际 RenderNode 绘制时,可在同一回调里推进下一帧动画。
退出释放
g.running.store(false);
OH_NativeVSync_DVSyncSwitch(g.vsync, false);
OH_NativeVSync_Destroy(g.vsync);
g.vsync = nullptr;
页面退出时停止轮询并调用 stop(),日志记录 VSYNC_RELEASE。
真机 Hilog
VSYNC_LAB_ENTER expected=60 permissionRequired=false
VSYNC_READY create=0 request=0 rate=0 dv=0
VSYNC_RELEASE callbacks=1401
验证结论
| 项目 | 结果 |
|---|---|
| NativeVSync 创建 | 返回 0,成功 |
| 下一帧请求 | 返回 0,成功提交 |
| 期望帧率范围 | 返回 0 |
| DVSync 开关 | 返回 0 |
| 回调与周期 | Native 释放日志累计 1401 次回调;页面快照可能因刷新时序显示 0 |
| 释放 | VSYNC_RELEASE 已记录 |
本篇完成了 NativeVSync 的最小接入、连续回调验证和释放闭环。后续将把同一回调接到 RenderNode/Canvas 的实际绘制,形成可见的帧时间线。
更多推荐

所有评论(0)