往期推文全新看点(文中附带全新鸿蒙5.0全栈学习笔录)
✏️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?
✏️ 嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~
✏️ 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?
✏️ 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?
✏️ 记录一场鸿蒙开发岗位面试经历~
✏️ 持续更新中……
概述
LTPO技术简介
LTPO的全称是“ Low Temperature Polycrystalline Oxide”,翻译成中文是“低温多晶氧化物”。这是OLED屏背板的一种驱动技术。通过将OLED驱动电路中漏电相关的TFT换成IGZO TFT,降低显示功耗。LTPO屏给产品带来1~120Hz自适应刷新率的能力。使应用在需要高刷新率的场景可使用高刷新率提升流畅性,在视频、静止等场景又可使用低刷新率降低显示功耗,提升续航。习惯上,用“LTPO”指代自适应刷新率技术。
特性介绍
LTPO指自适应刷新率技术。通过按需自适应调整显示刷新率,实现最优的性能和功耗体验。
说明
应用适配LTPO的好处:精细化场景帧率控制,降低场景负载,减少偶发卡顿,降低场景功耗。
场景策略建议
做到控件级帧率控制,降低系统因突发性负载增加带来的卡顿体验,同时在对高刷新率有要求的场景,主动适配确保流畅性体验。
不建议锁定最高帧率运行
不建议将ExpectedFrameRateRange中的expected、min、max都设置为120,否则会干扰系统的可变帧率机制运行,产生不必要的负载,进而影响到整机的性能和功耗。
主要原因有以下三点:
- ExpectedFrameRateRange中关键参数是expected(期望帧率),系统会优先按照expected设置的帧率执行。当系统难以满足expected帧率诉求时,会在min和max之间选一个更合适的帧率给到应用。
- 如果应用锁定120Hz,系统会优先满足应用的显式设置,按照120帧运行。此时手机功耗会显著增加,长时间运行会引起手机过热等严重影响用户体验的问题。同时也由于不必要的高帧率,会额外占据更多的算力,可能导致其他场景的响应受到不必要的延迟。
- 如果系统持续按照120Hz运行,从某种意义上来说此时系统的可变帧率能力已失效,这显然与可变帧率的设计原则不相符。
策略建议
类型 | 类型描述类型描述 | 帧帧率建议(案例) |
---|---|---|
高帧率场景 | 基本全屏的非持续动效 | 应用启动,退出,窗口转场动效,拖动窗口移动动效:90~120Hz |
中等帧率场景 | 变化区域大的持续型动效,非全屏的手势动效与转场动效 | 视频内弹幕,小说自动翻页动效:60Hz QQ首页左滑某一行消息动效:60Hz 微信右上角点击“+”号弹出应用内子窗口动效:60~120Hz 抖音内滑动切换视频,图库滑动切换图片动效:60Hz |
低帧率场景 | 小区域动效,微动效 | 小视频右下角转盘动效:1530Hz<br/>页面刷新加载转圈动效:2030Hz 滑动列表右侧拖动条消失动效:15~30Hz 复杂微动效,根据实际效果调整帧率 |
跟随源帧率场景 | 插画动效,固定源帧率动效 | 帧率跟随内容源,不建议长时间保持高帧率 购物应用首页图标帧动效 聊天表情包动效 导航主界面 |
功耗测试工具
显示手机实时刷新率
打开开发者模式中的"显示刷新频率"开关。具体操作:设置中搜索"开发者" -> “显示刷新频率”。
profiler工具测试手机功耗
1. 启动程序,并部署安装到真实手机上。
2. 打开工具profiler,并按图示选择需要监控的设备、app、进程。未启动app会出现设备、app等选项为空的情况,此时不能进行profiler性能分析。
(图中的黄色折线展示了整机的电量消耗,该折线的斜率为正时代表设备在耗电,斜率为负时代表设备在充电。)
3. 点击会话区“Realtime Monitor”页签上的启动按钮来即时控制实时监控界面的录制状态。
4. 将鼠标悬浮于所关心的泳道数据上时,界面上会出现当前时间点的时间标线以及含有当前时间点上泳道详细数据的Tooltips。更进一步,当您将鼠标悬浮于时间轴之上时,实时监控页面内的所有泳道均会以Tooltips展示出该时刻的数据。
本文采用的测试方式是让应用跑30s,以3s为一个节点,取设备从6s运行到21s5个节点的平均功耗。因为此时设备已平稳运行,功耗也趋于平稳,不再跳动。
使用场景
场景说明
在具备LTPO屏幕的设备上,基于显示内容的可变帧率能力,可以达到性能体验和功耗间的平衡。HarmonyOS支持可变帧率能力,开发者通过使用可变帧率接口,进行相关业务开发,可以享受可变帧率特性带来的功耗收益。
可变帧率能力支持开发者自定义应用业务的帧率,其常见的使用场景:
- 通过配置属性动画/显示动画的帧率属性参数,用于动画的绘制,具体可见请求动画绘制帧率。
- 通过申请一个独立的绘制帧率,用于UI的绘制,具体可见请求UI绘制帧率。
- 通过XComponent在Native侧申请独立的绘制帧率,用于游戏等自绘制内容的绘制,具体可见请求自绘制内容绘制帧率。
基于以上使用场景,结合众多实际开发案例,本文选取两个有代表性的案例展开介绍。
说明
开发者设置的期望帧率值不能代表最终实际效果,会受限于系统能力和屏幕刷新率。
基于LTPO实现循环动画
针对一些无限循环的动画效果,如转盘动画,需要尤为注意设置动画的可变帧率,如果长时间保持高帧率可能导致手机发热等现象发生。
效果展示
功耗对比
说明
使用DisplaySync去实现转盘动画,通过主动设置可变帧率,可以获取功耗的差异。
功耗测试方法参考章节2。
打开手机屏幕刷新率设置,可以看到刷新率变化;根据Profile工具,可以看到功耗变化如下所示。
从图中可以发现,当屏幕刷新率降低时,功耗会随之降低。
传入可变帧率(ExpectedFrameRateRange)时被屏幕感知,充分利用好屏幕的LTPO技术达到降低功耗的目的,屏幕的帧率没有时刻保持在最高帧率上刷新,所以功耗较低。
实现说明
首先需要导入模块
import { displaySync } from '@kit.ArkGraphics2D';
然后定义和构建DisplaySync对象
private backDisplaySyncSlow: displaySync.DisplaySync | undefined = undefined;
private backDisplaySyncFast: displaySync.DisplaySync | undefined = undefined;
定义图片组件并添加旋转方法
Row() {
Image($r('app.media.avatar'))
.height(40)
.width(40)
}
.rotate({
x: 0,
y: 0,
z: 1,
centerX: '50%',
centerY: '50%',
angle: this.rotateAngle
})
通过DisplaySync实例设置帧率和注册订阅函数。
let range : ExpectedFrameRateRange = {
expected: 30,
min: 0,
max: 120
};
this.backDisplaySyncSlow.setExpectedFrameRateRange(range); // 设置帧率
全部代码实现如下
import { displaySync } from '@kit.ArkGraphics2D';
@Entry
@Component
struct Index {
@State drawFirstSize: number = 25;
@State rotateAngle: number = 1;
@State drawSecondSize: number = 25;
private backDisplaySyncSlow: displaySync.DisplaySync | undefined = undefined;
private backDisplaySyncFast: displaySync.DisplaySync | undefined = undefined;
private isBigger_30: boolean = true;
aboutToDisappear() {
if (this.backDisplaySyncSlow) {
this.backDisplaySyncSlow.stop(); // DisplaySync使能关闭
this.backDisplaySyncSlow = undefined; // 实例置空
}
if (this.backDisplaySyncFast) {
this.backDisplaySyncFast.stop(); // DisplaySync使能关闭
this.backDisplaySyncFast = undefined; // 实例置空
}
}
CreateDisplaySyncSlow() {
// 定义期望绘制帧率
this.backDisplaySyncSlow = displaySync.create(); // 创建DisplaySync实例
let range: ExpectedFrameRateRange = {
expected: 30,
min: 0,
max: 120
};
this.backDisplaySyncSlow.setExpectedFrameRateRange(range); // 设置帧率
let draw30 = (intervalInfo: displaySync.IntervalInfo) => {
if (this.isBigger_30) {
this.rotateAngle += 1;
} else {
this.rotateAngle -= 1;
if (this.rotateAngle < 25) {
this.isBigger_30 = true;
}
}
};
this.backDisplaySyncSlow.on("frame", draw30); // 订阅frame事件和注册订阅函数
}
build() {
Column() {
Row() {
Image($r('app.media.avatar'))
.height(40)
.width(40)
}
.rotate({
x: 0,
y: 0,
z: 1,
centerX: '50%',
centerY: '50%',
angle: this.rotateAngle
})
Row() {
Button('Start')
.onClick(() => {
if (this.backDisplaySyncSlow === undefined) {
this.CreateDisplaySyncSlow();
}
if (this.backDisplaySyncSlow) {
this.backDisplaySyncSlow.start(); // DisplaySync使能开启
}
})
}
}
}
}
上述代码中,给DisplaySync设置一个可变帧率ExpectedFrameRateRange 可以让系统参考调整屏幕刷新率,若要取消设置可变帧率,可注释如下代码:
// 注释如下几行
// let range : ExpectedFrameRateRange = {
// expected: 30,
// min: 0,
// max: 120
// };
// this.backDisplaySyncSlow.setExpectedFrameRateRange(range);
说明
不建议将ExpectedFrameRateRange中的expected、min、max都设置为120,否则会干扰系统的可变帧率机制运行,产生不必要的负载,进而影响到整机的性能和功耗。
如setExpectedFrameRateRange({ expected: 120, min: 120, max: 120 })。
基于LTPO实现滑动条
效果展示
功耗对比
说明
使用animateTo实现转盘动画,通过主动设置可变帧率,可以获取功耗的差异。
功耗测试方法参考章节2。
开启手机帧率设置,我们可以看到帧率变化;根据Profile工具,可以看到功耗变化如下所示。
从图中可以发现,当屏幕刷新率降低时,功耗会随之降低。
传入可变帧率(ExpectedFrameRateRange)时被屏幕感知,充分利用好屏幕的LTPO技术达到降低功耗的目的,屏幕的帧率没有时刻保持在最高帧率上刷新,所以功耗较低。
代码实现
在滑动条里添加onVisibleAreaChange事件,在其回调函数里使滑块的当前值加到100。
// src/main/ets/view/SampleUnitAVPlayView.ets
Slider({ value: this.curTime, min: 0, max: 100 })
.enabled(false)
.height(4)
.width(this.sliderWidth)
.trackThickness(3)
.blockColor(Color.Red)
.blockSize({ width: 4, height: 4 })
.onVisibleAreaChange([0.0, 1.0], (isVisible: boolean, currentRatio: number) => {
if (isVisible) {
animateTo({
duration: DURATION,
iterations: -1,
expectedFrameRateRange: {
expected: 30,
min: 0,
max: 120,
},
}, () => {
if (this.curTime >= 100) {
this.curTime = 0;
}
for (let i = 0; i < 101; i++) {
this.curTime += 1;
}
})
}
})
总结
综上所述,使用LTPO技术可以控制各个动效的刷新率,从而降低屏幕刷新率,进而控制功耗,为用户带来更加持久的续航时间和更高品质的使用体验。因此在开发业务时推荐使用可变帧率接口,可以享受可变帧率特性带来的功耗收益。