版本说明:LTPO 特性自 Flutter
3.27.5-ohos-1.0.6版本开始支持。
LTPO功能是指屏幕动态帧率,在屏幕刷新率设置为“智能”时,应用可根据当前场景自动切换合适的帧率。
Flutter框架帧率现状:在屏幕刷新率设置为“智能”时,其帧率策略与屏幕刷新率设置为“高”时一致。手指触摸屏幕时,屏幕刷新率为120帧;手指离开屏幕后,屏幕刷新率保持3s的120帧;3s后无操作,屏幕刷新率降低为60帧。
注意:LTPO特性依赖OpenHarmony API 20,请在API 20及以上的ROM中验证。
2.适配场景
| 序号 | 场景 |
|---|---|
| 1 | 自定义平移动画 |
| 2 | 转场平移动画 |
| 3 | 滚动列表抛滑 |
| 4 | 轮播图 |
3.应用适配依赖
| 依赖顺序 | 依赖项 | 说明 |
|---|---|---|
| 1 | deveco-studio | IDE工具 |
| 2 | flutter_flutter | 集成了LTPO功能的flutter sdk |
| 3 | LTPO配置文件 | 配置LTPO功能开关和帧率策略 |
| 4 | 匹配版本要求 | 系统能力支持的最低版本 |
4.详情
4.1deveco-studio
deveco-studio需要更新新版本,点击下方链接下载最新DevEco Studio.
链接:https://developer.huawei.com/consumer/cn/download/deveco-studio
4.2flutter_flutter
LTPO功能跟随flutter_flutter代码仓版本发布,请使用flutter_flutter代码仓的3.27.5-ohos-1.0.2分支进行具备LTPO功能的flutter应用开发。
链接:https://gitcode.com/CPF-Flutter/flutter_flutter/tree/3.27.5-ohos-1.0.2
4.3LTPO配置文件
LTPO配置文件有动态帧率开关,平移动画的帧率映射表,以及缩放和旋转的帧率映射表。
| 子项 | 描述 | 类型 |
| ---- | ---- | ---- |
| SWITCH | 动态帧率开关 | 整型。0-关闭;1-开启 |
| TRANSLATE | 平移动画的帧率映射表,
不建议修改帧率映射表中的元素。 | 数组。每个元素由序号、最小速度、最大速度、期望帧率组成。 |
| SCALE | 平移动画的帧率映射表,
不建议修改帧率映射表中的元素。
当前未实现 | 数组。每个元素由序号、最小速度、最大速度、期望帧率组成。 |
| ROTATION | 平移动画的帧率映射表,
不建议修改帧率映射表中的元素。
当前未实现 | 数组。每个元素由序号、最小速度、最大速度、期望帧率组成。 |
当前帧率映射表如下:
| 序号 | 最低滑动速度 | 最高滑动速度 | 帧率 |
| ---- | ---- | ---- | ---- |
| 1 | 800 | 无限大 | 90 |
| 2 | 77 | 800 | 120 |
| 3 | 46 | 77 | 90 |
| 4 | 10 | 46 | 72 |
| 5 | 0 | 10 | 60 |
注意:实际屏幕帧率由系统决策。
配置文件framesconfig.json,存放在ArkUI应用工程中Flutter模块的src/main/resources/rawfile目录下,与flutter_assets同级目录。
详细说明:
- framesconfig.json是LTPO的配置文件,可配置使能开关,当前默认使能。
- 配置文件预置了平移动画的速率映射帧率挡位,根据动画的平移速率来决定屏幕刷新率。默认映射帧率挡位配置,不推荐改动。
- 配置文件预置在模板应用工程中,默认存在新建的flutter应用工程中。已存在的flutter应用工程,需要适配切换flutter 3.27版本或更高版本,并手动拷贝framesconfig.json文件到应用工程ohos/entry/src/main/resources/rawfile路径下。
其原型文件在
https://gitcode.com/CPF-Flutter/flutter_flutter/blob/3.27.5-ohos-1.0.2/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/base/profile/framesconfig.json
4.4匹配版本要求
打开“设置”,进入“关于本机”,查看软件版本是否为《6.0.0.110(SP96C00E110R4P8)》及以上。
5.适配流程
- 更新deveco-studio的IDE工具,至少使用DevEco Studio 6.0.0 Release版本,其中包含所依赖的api 20接口。
- 下载适配了LTPO功能的flutter_flutter代码仓,并添加进环境变量。
- 命令行窗口执行"flutter doctor -v",确认flutter路径是否为适配了ltpo功能的flutter_flutter代码仓,其分支是否为3.27.5-ohos-1.0.2及以上,确保适配应用是flutter 3.27 版本的。
- 应用工程里的ltpo配置文件framesconfig.json确认是否存在。如果是新建的flutter应用工程,ltpo配置文件默认存在应用模板里;如果是已存在的应用工程,需要手动拷贝framesconfig.json文件到应用工程ohos/entry/src/main/resources/rawfile路径下。
- 确认LTPO配置文件使能开关打开。请查看framesconfig.json文件“SWITCH”选项是否为1,不为1则修改为1。
6.验证流程
- 检查手机版本是否匹配版本要求。不匹配的情况下,联系接口人推送系统版本。
- 当前系统有帧率策略管控,需要联系接口人进行系统帧率策略云推。
- 开启“智能”刷新。“设置” > “显示和亮度” > “屏幕刷新率”。
- 开启“显示刷新频率”。“设置” > “系统” > “开发者选项”,调试那一栏下。开启后左上角显示两个数字,左侧为帧率挡位,即期望帧率;右侧为实时帧率。主要关心左侧的数字。(如果只有一个数字,即为帧率挡位)
- 打开应用中带有Flutter框架的滚动组件页面。
- 页面抛滑。
- 观察抛滑过程,可以看到显示帧率根据页面滑动速度从120fps先降低到90fps,最后停止滑动后降低到60fps。如下图所示:
7.常见问题
动画页面切换后台,动画未暂停,仍然在执行。屏幕刷新率未下降。
有以下建议:
合理选择标签页页面的TabController
TabController的创建有两种形式,一种是使用系统的DefaultTabController,第二种是自己定义一个TabController实现SingleTickerProviderStateMixin。
- 无状态控件(StatelessWidget)搭配DefaultTabController
- 有状态控件(StatefulWidget)搭配TabController
// 示例代码classTabsPageextendsStatefulWidget{@overrideState<TabsPage> createState() => _TabsPageState(); }class_TabsPageStateextendsState<TabsPage>withSingleTickerProviderStateMixin{ lateTabController_tabController;@overridevoid initState() {super.initState(); _tabController =newTabController( vsync:this, length:3// 设置TabBarView数量); }@overridevoid dispose() { _tabController.dispose();super.dispose(); }@overrideWidgetbuild(BuildContextcontext) { ...TabBar( controller: _tabController, tabs: <Widget>[ ... ] ), ...TabBarView( controller: _tabController, children: <Widget>[ ... ] ), } }TabView页签切换停止动画
有状态控件(StatefulWidget)生命周期deactivate,当框架从树中移除此 State 对象时将会调用此方法。可在此生命周期回调deactivate对AnimationController进行stop的操作。
如果是一个基于this的vsync周期循环的动画,重新进入页面后会自动播放,无须手动启动动画。
// 示例代码classAnimationPageextendsStatefulWidget{@override_AnimationPageState createState() => _AnimationPageState(); }class_AnimationPageStateextendsState<AnimationPage>withSingleTickerProviderStateMixin{ lateAnimationController_controller;@overridevoid deactivate() {super.deactivate(); _controller.stop(); }@overridevoid initState() {super.initState(); _controller =AnimationController(duration:Duration(seconds:4), vsync:this) ..addListener(() { setState(() {}); }) ..repeat(reverse:true); ... } }8.参考资料
可变帧率简介
https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/graphics/displaysync-overview.md
基于LTPO的低功耗设计
https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-ltpo-description
NativeVSync开发指导 (C/C++)
https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/graphics/native-vsync-guidelines.md
NativeVsync的相关函数
https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-arkgraphics2d/capi-native-vsync-h.md