HarmonyOS 7 新特性(十六)|LTPO 可变帧率:流畅与功耗的动态平衡

HarmonyOS 7 延续 ArkGraphics 2D 的 LTPO 可变帧率能力。本文讨论如何让应用主动表达帧率需求,并用运行证据平衡流畅度、温升与功耗。
全程维持最高刷新率看起来最顺滑,却不一定是最佳方案。静态阅读、24fps 视频、列表滚动、画布拖动和游戏对战对刷新需求完全不同。ArkGraphics 2D 支持为不同内容申请不同帧率,同一窗口也可以多帧率共存。
真正的难点不是“设置 120”,而是识别业务状态、避免频率抖动、处理系统拒绝和证明功耗收益。
一、先定义业务场景
不要按页面名称配置帧率,而要按交互状态建模:静止、缓慢滚动、快速滚动、拖动、过渡动画、视频播放、窗口失焦、后台。
type FrameScene =
| 'idle'
| 'reading'
| 'scrolling'
| 'dragging'
| 'animation'
| 'video'
| 'background'
interface FrameRequest {
scene: FrameScene
preferredFps: number
minDurationMs: number
reason: string
}
业务状态是稳定语义,具体帧率由平台策略映射,避免页面散落魔法数字。
二、建立统一帧率策略表
const framePolicy: Record<FrameScene, FrameRequest> = {
idle: { scene: 'idle', preferredFps: 30, minDurationMs: 500, reason: 'static' },
reading: { scene: 'reading', preferredFps: 30, minDurationMs: 800, reason: 'text' },
scrolling: { scene: 'scrolling', preferredFps: 60, minDurationMs: 300, reason: 'scroll' },
dragging: { scene: 'dragging', preferredFps: 120, minDurationMs: 200, reason: 'direct-manipulation' },
animation: { scene: 'animation', preferredFps: 90, minDurationMs: 300, reason: 'transition' },
video: { scene: 'video', preferredFps: 60, minDurationMs: 1000, reason: 'playback' },
background: { scene: 'background', preferredFps: 15, minDurationMs: 1000, reason: 'invisible' }
}
数值只是工程示例,具体申请方式、支持区间和实际帧率以设备与当前 ArkGraphics 2D 文档为准。
三、用状态机处理优先级
同一时刻可能有多个请求:视频播放需要 60fps,用户拖动控制条希望更高,弹窗动画也在运行。协调器应选择当前最高必要等级,而不是最后一次调用覆盖前面状态。
class FrameRateCoordinator {
private requests = new Map<string, FrameRequest>()
acquire(owner: string, request: FrameRequest) {
this.requests.set(owner, request)
this.applyHighestNecessaryRate()
}
release(owner: string) {
this.requests.delete(owner)
this.scheduleDownshift()
}
private applyHighestNecessaryRate() {
const fps = Math.max(30, ...[...this.requests.values()]
.map(x => x.preferredFps))
displayAdapter.requestFrameRate(fps)
}
}
组件销毁、离屏或手势取消时必须 release,否则页面会长期停在高刷新率。

四、升频快,降频慢
手指轻微移动可能让状态在 idle 与 scrolling 之间反复切换。进入拖动可以立即升频,退出则等待交互稳定一段时间再回落,这就是迟滞策略。
private scheduleDownshift() {
clearTimeout(this.downshiftTimer)
this.downshiftTimer = setTimeout(() => {
this.applyHighestNecessaryRate()
}, 400)
}
窗口失焦、进入后台和开启省电策略属于强制回落条件,不需要等待迟滞。
五、同一窗口多帧率共存
播放 24fps 电影时,画面不需要被强行复制到 120fps;控制条出现、弹幕滚动和手势拖动可以临时使用更高刷新。暂停后,视频区域可以降频,进度文字只在数值变化时刷新。
需要分开观察内容生产速率、合成速率和屏幕送显。若只记录窗口平均帧率,很难判断哪个区域制造了额外功耗。
六、申请值不等于实际值
业务申请只是意图,系统还会结合设备能力、温度、电量和全局调度决定实际送显。应用不能因为请求 120fps 就在逻辑中假定每 8.3ms 一帧,应使用真实时间差计算动画进度。
function updateAnimation(nowMs: number) {
const delta = Math.min(nowMs - lastFrameMs, 50)
progress = Math.min(1, progress + delta / durationMs)
lastFrameMs = nowMs
}
七、无障碍和省电策略优先
用户开启“减少动态效果”时,降低非必要动画并直接跳到终态;省电模式下限制装饰性高帧率,但手写、拖动和关键反馈仍要可操作。不能用低功耗为理由让点击反馈明显延迟。
八、性能埋点设计
每次策略切换记录 scene、请求值、实际帧时间、持续时间、设备等级、温控状态和电量区间。不要记录用户内容。指标至少包括平均帧时间、P95 长帧、掉帧比例、功耗和温升。
trace.record('frame-policy', {
scene: request.scene,
requestedFps: request.preferredFps,
actualFrameMs: metrics.frameTime,
thermal: device.thermalLevel,
powerSaving: device.powerSaving
})
九、自动化验证策略释放
describe('FrameRateCoordinator', () => {
it('keeps high fps while any high-priority owner remains', () => {
coordinator.acquire('video', framePolicy.video)
coordinator.acquire('drag', framePolicy.dragging)
coordinator.release('drag')
expect(adapter.lastRequestedFps).toBe(60)
})
it('releases request after component disappears', () => {
component.aboutToDisappear()
expect(coordinator.hasOwner(component.id)).toBe(false)
})
})
真机还要覆盖连续滚动、快速手势、视频控制条、分屏、自由窗口、锁屏恢复和长时间温控。
十、上线清单
- 帧率按业务状态而非页面名称配置;
- 所有申请都有 owner 和 release;
- 多请求按最高必要等级协调;
- 升频与降频有迟滞策略;
- 动画使用真实时间差,不依赖固定帧数;
- 减少动态和省电策略能够覆盖默认配置;
- 申请帧率、实际帧时间和功耗同时度量;
- 不支持设备回到系统默认调度。

结语
LTPO 可变帧率的核心不是追求最高数字,而是让每段内容只使用完成体验所需的刷新预算。用业务状态、统一协调器、迟滞和真机指标管理帧率,才能同时获得跟手性与续航收益。
官方参考
- ArkGraphics 2D:https://developer.huawei.com/consumer/cn/sdk/arkgraphics-2d/
- HarmonyOS 7 新能力一览:https://developer.huawei.com/consumer/cn/features/
更多推荐



所有评论(0)