Flutter-OH插件fps鸿蒙适配实战:从零到一完整指南
随着鸿蒙生态的快速发展,越来越多的Flutter开发者开始关注如何将现有的Flutter插件适配到鸿蒙平台。本文将以插件为例,详细讲解从Flutter原生插件到鸿蒙平台的完整适配过程,包括技术选型、代码实现、构建配置等关键环节。架构设计: 遵循Flutter插件标准架构,保持Dart层API一致API映射: 将平台原生API映射到鸿蒙等效API生命周期管理: 正确实现插件生命周期方法,避免资源泄漏
Flutter-OH插件fps鸿蒙适配实战:从零到一完整指南

前言
随着鸿蒙生态的快速发展,越来越多的Flutter开发者开始关注如何将现有的Flutter插件适配到鸿蒙平台。本文将以performance_fps插件为例,详细讲解从Flutter原生插件到鸿蒙平台的完整适配过程,包括技术选型、代码实现、构建配置等关键环节。
一、项目背景
performance_fps是一个用于实时计算应用FPS(每秒帧数)的Flutter插件,支持Android和iOS平台。它可以帮助开发者监控应用的性能表现,是性能优化的重要工具。我们的目标是将这个插件适配到鸿蒙平台,使其能够支持Flutter OpenHarmony(OH)应用。
原插件架构
原插件采用标准的Flutter插件架构:
performance_fps/
├── lib/ # Dart层,提供统一的API接口
│ └── plugin/fps_plugin.dart # MethodChannel通信层
├── android/ # Android原生实现
│ └── src/main/java/com/lib/fps/fps/FpsPlugin.java
└── ios/ # iOS原生实现
└── Classes/FpsPlugin.m
核心功能
通过MethodChannel调用原生平台API获取屏幕刷新率:
// Dart层接口
static Future<double> get getRefreshRate async {
final double fpsHz = await _channel.invokeMethod('getRefreshRate') ?? 60;
return fpsHz;
}
二、鸿蒙平台适配技术选型
2.1 开发环境
在进行适配之前,需要准备以下开发环境:
- Flutter SDK: 3.35.8-ohos-0.0.2 或更高版本
- DevEco Studio: 6.1.0 或更高版本
- HarmonyOS SDK: 6.0.1(21) 或更高版本
2.2 技术栈选择
鸿蒙平台适配主要涉及以下技术:
- 编程语言: ArkTS(TypeScript的鸿蒙方言)
- UI框架: ArkUI(鸿蒙声明式UI框架)
- 构建工具: Hvigor(鸿蒙构建系统)
- 插件框架: Flutter OHOS Plugin Framework
- 显示同步API:
@kit.ArkGraphics2D中的displaySync
2.3 核心API对比
| 功能 | Android | iOS | HarmonyOS |
|---|---|---|---|
| 屏幕刷新率获取 | WindowManager.getRefreshRate() | CADisplayLink | displaySync.DisplaySync |
| 语言 | Java | Objective-C | ArkTS |
| 构建系统 | Gradle | CocoaPods | Hvigor |
| 插件框架 | FlutterPlugin | FlutterPlugin | FlutterPlugin |
三、项目结构调整
3.1 创建鸿蒙平台目录
在插件根目录下创建ohos目录,结构如下:
flutter_fps/
├── ohos/
│ ├── src/
│ │ └── main/
│ │ ├── ets/
│ │ │ └── components/
│ │ │ └── plugin/
│ │ │ └── FlutterFpsPlugin.ets
│ │ └── module.json5
│ ├── index.ets
│ ├── build-profile.json5
│ ├── oh-package.json5
│ └── hvigorfile.ts
3.2 配置pubspec.yaml
在pubspec.yaml中添加鸿蒙平台配置:
flutter:
plugin:
platforms:
android:
package: com.lib.fps.fps
pluginClass: FpsPlugin
ios:
pluginClass: FpsPlugin
ohos:
pluginClass: FpsPlugin
四、核心代码实现
4.1 插件入口文件
文件: ohos/index.ets
import FlutterFpsPlugin from './src/main/ets/components/plugin/FlutterFpsPlugin';
export default FlutterFpsPlugin;
这是插件的入口文件,Flutter构建系统会通过这个文件加载插件实现。
4.2 模块配置
文件: ohos/src/main/module.json5
{
"module": {
"name": "performance_fps",
"type": "har",
"deviceTypes": [
"default",
"tablet"
]
}
}
关键配置说明:
name: 模块名称,需与插件名称保持一致type: "har"表示这是一个HarmonyOS Archive(类似Android的AAR)deviceTypes: 支持的设备类型
4.3 构建配置
文件: ohos/build-profile.json5
{
"apiType": "stageMode",
"buildOption": {},
"targets": [
{
"name": "default"
}
]
}
apiType: "stageMode"表示使用Stage模型(鸿蒙推荐的应用模型)。
4.4 插件实现
文件: ohos/src/main/ets/components/plugin/FlutterFpsPlugin.ets
这是整个适配的核心文件,完整的实现如下:
import {
FlutterPlugin,
FlutterPluginBinding,
MethodCall,
MethodCallHandler,
MethodChannel,
MethodResult,
} from '@ohos/flutter_ohos';
import { displaySync } from '@kit.ArkGraphics2D';
/** FlutterFpsPlugin **/
export default class FlutterFpsPlugin implements FlutterPlugin, MethodCallHandler {
private channel: MethodChannel | null = null;
private backDisplaySync: displaySync.DisplaySync = displaySync.create();
private passframeInfo: Array<displaySync.IntervalInfo> = []
private fps: number = 0
constructor() {
}
getUniqueClassName(): string {
return "FlutterFpsPlugin"
}
onAttachedToEngine(binding: FlutterPluginBinding): void {
this.channel = new MethodChannel(binding.getBinaryMessenger(), "fps");
this.channel.setMethodCallHandler(this)
}
onDetachedFromEngine(binding: FlutterPluginBinding): void {
if (this.channel != null) {
this.channel.setMethodCallHandler(null)
}
this.backDisplaySync?.stop();
}
onMethodCall(call: MethodCall, result: MethodResult): void {
if (call.method == "getPlatformVersion") {
result.success("OpenHarmony ^ ^ ")
} else if (call.method == "getRefreshRate") {
let callback = (frameInfo: displaySync.IntervalInfo) => {
this.passframeInfo.push(frameInfo);
if (this.passframeInfo.length >= 2) {
let tmp = this.passframeInfo[1].timestamp - this.passframeInfo[0].timestamp;
let result = 1000000000 / Number.parseInt(tmp.toString());
this.fps = result;
this.passframeInfo.shift();
}
};
this.backDisplaySync?.on("frame", callback);
this.backDisplaySync?.start();
result.success(this.fps)
}
else {
result.notImplemented()
}
}
}
五、关键技术实现详解
5.1 Flutter插件接口实现
5.1.1 接口继承
export default class FlutterFpsPlugin implements FlutterPlugin, MethodCallHandler
插件需要实现两个核心接口:
FlutterPlugin: 插件生命周期管理MethodCallHandler: 方法调用处理
5.1.2 插件生命周期
onAttachedToEngine(binding: FlutterPluginBinding): void {
this.channel = new MethodChannel(binding.getBinaryMessenger(), "fps");
this.channel.setMethodCallHandler(this)
}
onDetachedFromEngine(binding: FlutterPluginBinding): void {
if (this.channel != null) {
this.channel.setMethodCallHandler(null)
}
this.backDisplaySync?.stop();
}
onAttachedToEngine: 插件附加到Flutter引擎时调用,创建MethodChannel并设置方法处理器onDetachedFromEngine: 插件从Flutter引擎分离时调用,清理资源
注意: 必须在onDetachedFromEngine中调用backDisplaySync?.stop(),否则会导致资源泄漏。
5.2 FPS计算原理
5.2.1 HarmonyOS显示同步API
鸿蒙提供了displaySync API用于实现显示同步,核心类包括:
displaySync.DisplaySync: 显示同步器displaySync.IntervalInfo: 帧间隔信息,包含时间戳
5.2.2 FPS计算算法
原插件的实现方式对比:
Android实现(直接获取刷新率):
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
float refreshRate = windowManager.getDefaultDisplay().getRefreshRate();
iOS实现(使用CADisplayLink):
- (double)displayRefreshRate:(CADisplayLink *)link {
if (@available(iOS 10.3, *)) {
NSInteger preferredFPS = link.preferredFramesPerSecond;
if (preferredFPS != 0) {
return @(preferredFPS).doubleValue;
}
return @([UIScreen mainScreen].maximumFramesPerSecond).doubleValue;
} else {
return 60.0;
}
}
HarmonyOS实现(通过帧间隔计算):
let callback = (frameInfo: displaySync.IntervalInfo) => {
this.passframeInfo.push(frameInfo);
if (this.passframeInfo.length >= 2) {
let tmp = this.passframeInfo[1].timestamp - this.passframeInfo[0].timestamp;
let result = 1000000000 / Number.parseInt(tmp.toString());
this.fps = result;
this.passframeInfo.shift();
}
};
this.backDisplaySync?.on("frame", callback);
this.backDisplaySync?.start();
5.2.3 算法解析
- 收集帧信息: 使用队列
passframeInfo存储最近的帧信息 - 计算时间差: 获取两帧之间的时间间隔(纳秒级精度)
- 计算FPS:
FPS = 1,000,000,000 / 时间间隔纳秒 - 实时更新: 每次收到新帧时更新FPS值
为什么这样实现?
鸿蒙的displaySync API不直接提供刷新率,而是提供了帧间隔信息。因此需要通过计算两帧之间的时间间隔来推导FPS。这种方法的优点是:
- 实时性更强,反映实际渲染性能
- 不依赖系统静态配置
- 可以检测到动态刷新率变化(如自适应刷新率)
5.3 平台差异处理
5.3.1 时间精度
- Android: 毫秒级
- iOS: 毫秒级
- HarmonyOS: 纳秒级(9位时间戳)
因此HarmonyOS实现中使用1000000000(10亿)作为转换基数。
5.3.2 错误处理
this.backDisplaySync?.on("frame", callback);
this.backDisplaySync?.start();
使用可选链操作符?.确保在backDisplaySync为null时不会崩溃。
六、构建系统配置
6.1 包管理配置
文件: ohos/oh-package.json5
{
"name": "flutter_fps",
"version": "1.0.0",
"description": "Please describe the basic information.",
"main": "index.ets",
"author": "",
"license": "Apache-2.0",
"dependencies": {}
}
这是鸿蒙的包管理文件,类似于npm的package.json。
6.2 构建脚本
文件: ohos/hvigorfile.ts
import { harTasks } from '@ohos/hvigor-ohos-plugin';
export default {
system: harTasks,
plugins:[]
}
Hvigor是鸿蒙的构建工具,类似于Gradle。这里配置了HAR包的构建任务。
七、测试与验证
7.1 创建示例应用
在example/ohos目录下创建鸿蒙示例应用,测试插件功能:
// example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:performance_fps/performance_fps.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
double _fps = 0.0;
void initState() {
super.initState();
_getFps();
}
Future<void> _getFps() async {
double fps = await FpsPlugin.getRefreshRate;
setState(() {
_fps = fps;
});
}
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('FPS Demo')),
body: Center(
child: Text('Current FPS: $_fps'),
),
),
);
}
}
7.2 兼容性测试
经过测试,本插件在以下环境中运行正常:
| Flutter版本 | HarmonyOS SDK | DevEco Studio | 测试结果 |
|---|---|---|---|
| 3.22.0-ohos | 5.0.0(12) | 5.1.0.828 | ✓ 通过 |
| 3.35.8-ohos-0.0.2 | 6.0.1(21) | 6.1.0 | ✓ 通过 |
八、常见问题与解决方案
8.1 插件未找到
问题: 运行时报错"Plugin not found"
解决方案:
- 确认
pubspec.yaml中正确配置了ohos平台 - 检查
ohos/index.ets是否正确导出插件类 - 执行
flutter clean后重新构建
8.2 MethodChannel调用失败
问题: 调用getRefreshRate时无响应
解决方案:
- 确认Channel名称一致(Dart层和原生层都应为"fps")
- 检查
onMethodCall方法是否正确实现 - 确认
setMethodCallHandler已调用
8.3 FPS计算不准确
问题: 返回的FPS值异常(如0或极大值)
解决方案:
- 确保
passframeInfo队列长度至少为2 - 检查时间戳计算是否正确(纳秒级精度)
- 验证
displaySync是否正常启动
8.4 资源泄漏
问题: 长时间运行后内存增长
解决方案:
- 确保
onDetachedFromEngine中调用backDisplaySync?.stop() - 检查是否正确清理MethodChannel处理器
- 使用DevEco Studio的Profiler工具监控内存
九、最佳实践
9.1 代码组织
- 将平台相关代码放在
ohos/src/main/ets/目录下 - 使用清晰的命名规范,如
FlutterFpsPlugin - 添加必要的注释说明关键逻辑
9.2 错误处理
try {
// 插件逻辑
} catch (error) {
result.error("PLUGIN_ERROR", error.message, null);
}
9.3 生命周期管理
onDetachedFromEngine(binding: FlutterPluginBinding): void {
// 清理所有资源
this.channel?.setMethodCallHandler(null);
this.backDisplaySync?.stop();
this.backDisplaySync = null;
this.channel = null;
}
9.4 性能优化
- 避免频繁创建和销毁对象
- 使用对象池复用对象
- 合理设置帧采样频率
十、总结与展望
10.1 核心要点回顾
- 架构设计: 遵循Flutter插件标准架构,保持Dart层API一致
- API映射: 将平台原生API映射到鸿蒙等效API
- 生命周期管理: 正确实现插件生命周期方法,避免资源泄漏
- 构建配置: 完善的鸿蒙构建系统配置
- 测试验证: 多版本兼容性测试
10.2 技术难点
- API差异处理: 鸿蒙的
displaySync与Android/iOS的刷新率获取API差异较大 - 时间精度转换: 纳秒级时间戳的计算和转换
- 构建系统迁移: 从Gradle/CocoaPods迁移到Hvigor
10.3 未来改进方向
- 自适应刷新率支持: 检测并支持动态刷新率变化
- 性能监控增强: 添加丢帧、卡顿等更多性能指标
- 可视化工具: 提供FPS实时监控UI组件
- 多平台统一: 进一步抽象平台差异,提供更统一的API
10.4 给开发者的建议
- 深入了解鸿蒙API: 熟悉
@kit.ArkGraphics2D等核心Kit - 参考官方文档: 查阅Flutter OHOS官方插件开发指南
- 充分测试: 在不同设备和系统版本上进行测试
- 社区交流: 积极参与鸿蒙开发者社区,分享经验
十一、参考资料
结语
通过本文的详细介绍,相信读者已经掌握了Flutter插件适配鸿蒙平台的完整流程。随着鸿蒙生态的不断完善,越来越多的Flutter开发者将参与到鸿蒙应用开发中。希望本文能为开发者提供有价值的参考,推动Flutter在鸿蒙平台的发展。
让我们一起见证鸿蒙生态的繁荣!
更多推荐



所有评论(0)