鸿蒙 Flutter 混合开发:原生组件嵌入与插件化实战
在鸿蒙(HarmonyOS)应用开发中,纯 Flutter 开发虽然能实现跨端复用,但面对鸿蒙系统特有的原生能力(如方舟卡片、服务卡片、系统级弹窗)时,往往需要与鸿蒙原生组件进行混合开发。本文将聚焦鸿蒙 Flutter 混合开发,讲解如何在 Flutter 页面中嵌入鸿蒙原生组件、开发自定义 Flutter 插件,并结合完整代码案例,帮助开发者打通 Flutter 与鸿蒙原生的双向融合通道。
一、鸿蒙 Flutter 混合开发核心模式
鸿蒙 Flutter 混合开发主要有两种核心模式,适用于不同的业务场景:
- Flutter 嵌入原生:在鸿蒙原生页面中嵌入 Flutter 模块,适用于已有原生项目需扩展跨端功能的场景。
- 原生嵌入 Flutter:在 Flutter 页面中嵌入鸿蒙原生组件(如
TextClock、ArkCard),适用于需要调用鸿蒙独有原生 UI 的场景。 - 插件化开发:将鸿蒙原生能力封装为 Flutter 插件,供多个 Flutter 项目复用,是混合开发的最佳实践。
本文重点讲解原生组件嵌入 Flutter和自定义插件开发两种场景。
二、案例 1:Flutter 页面中嵌入鸿蒙原生组件
鸿蒙系统提供了大量特色原生组件,例如TextClock(系统时钟)、RoundProgressBar(圆形进度条)等。通过PlatformView,我们可以在 Flutter 页面中直接嵌入这些原生组件,实现 UI 的混合渲染。
前置条件
- 已配置鸿蒙 DevEco Studio 和 Flutter 环境,确保两者版本兼容。
- 鸿蒙项目已开启
ohos_ability和flutter的依赖支持。
步骤 1:鸿蒙原生端实现PlatformView
首先在鸿蒙原生项目中创建一个原生组件,并实现PlatformView接口,供 Flutter 端调用。我们以嵌入鸿蒙原生圆形进度条为例。
1. 创建原生进度条组件
在鸿蒙原生项目的entry > src > main > java > com > example > harmonyflutter > widget目录下,创建NativeProgressView.java:
package com.example.harmonyflutter.widget;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.RoundProgressBar;
import ohos.agp.utils.Color;
import ohos.app.Context;
public class NativeProgressView extends RoundProgressBar {
// 进度值
private int progress = 0;
public NativeProgressView(Context context) {
super(context);
initView();
}
public NativeProgressView(Context context, AttrSet attrSet) {
super(context, attrSet);
initView();
}
private void initView() {
// 设置进度条样式
this.setProgressColor(new Color(0xFF007DFF)); // 鸿蒙系统蓝
this.setMaxValue(100);
this.setRadius(50); // 圆形半径
this.setProgressWidth(10); // 进度条宽度
this.setProgress(progress);
}
// 提供设置进度的方法,供Flutter调用
public void setProgressValue(int progress) {
this.progress = progress;
this.setProgress(progress);
}
// 提供获取当前进度的方法
public int getProgressValue() {
return this.progress;
}
}
2. 实现PlatformView和PlatformViewFactory
在同一目录下创建ProgressViewFactory.java,实现PlatformViewFactory和PlatformView接口,负责创建和管理原生组件:
package com.example.harmonyflutter.widget;
import ohos.ace.ability.AceInternalAbility;
import ohos.ace.plugin.platformview.PlatformView;
import ohos.ace.plugin.platformview.PlatformViewFactory;
import ohos.app.Context;
import java.util.Map;
public class ProgressViewFactory extends PlatformViewFactory {
private Context context;
public ProgressViewFactory(Context context) {
this.context = context;
}
@Override
public PlatformView create(String viewType, String id, Map<String, Object> params) {
// 匹配Flutter端传入的viewType
if ("native_progress_view".equals(viewType)) {
return new NativeProgressPlatformView(context, id, params);
}
return null;
}
// 实现PlatformView接口
static class NativeProgressPlatformView implements PlatformView {
private NativeProgressView progressView;
private Context context;
public NativeProgressPlatformView(Context context, String id, Map<String, Object> params) {
this.context = context;
this.progressView = new NativeProgressView(context);
// 初始化进度(可选,从Flutter传入参数)
if (params.containsKey("initProgress")) {
int initProgress = (int) params.get("initProgress");
progressView.setProgressValue(initProgress);
}
}
@Override
public Component getComponent() {
// 返回原生组件
return progressView;
}
@Override
public void dispose() {
// 组件销毁时释放资源
progressView = null;
}
// 暴露方法给Flutter调用,更新进度
public void updateProgress(int progress) {
if (progressView != null) {
progressView.setProgressValue(progress);
}
}
}
}
3. 注册PlatformView到 Flutter 引擎
在MainAbilitySlice.java中,将自定义PlatformViewFactory注册到 Flutter 引擎:
import com.example.harmonyflutter.widget.ProgressViewFactory;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.platform.PlatformViewRegistry;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
FlutterEngine flutterEngine = new FlutterEngine(getContext());
// 注册PlatformView
PlatformViewRegistry registry = flutterEngine.getPlatformViewsController().getRegistry();
registry.registerViewFactory("native_progress_view", new ProgressViewFactory(getContext()));
// 执行Flutter入口
flutterEngine.getDartExecutor().executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
);
}
步骤 2:Flutter 端嵌入原生组件
在 Flutter 项目中,通过AndroidView(鸿蒙系统兼容 AndroidView API)来加载原生组件,并实现进度的双向通信。
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '鸿蒙原生组件嵌入Flutter',
theme: ThemeData(primarySwatch: Colors.blue),
home: const NativeComponentPage(),
);
}
}
class NativeComponentPage extends StatefulWidget {
const NativeComponentPage({super.key});
@override
State<NativeComponentPage> createState() => _NativeComponentPageState();
}
class _NativeComponentPageState extends State<NativeComponentPage> {
// 进度值
int _progress = 30;
// 与原生通信的MethodChannel
static const MethodChannel _channel = MethodChannel('com.example.progress_view');
// 更新进度
void _updateProgress() {
setState(() {
_progress = (_progress + 10) % 100;
});
// 调用原生方法更新进度
_channel.invokeMethod('updateProgress', {'progress': _progress});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('嵌入鸿蒙原生进度条')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// 嵌入鸿蒙原生进度条组件
SizedBox(
width: 100,
height: 100,
child: AndroidView(
// 与原生注册的viewType一致
viewType: 'native_progress_view',
// 初始化参数
creationParams: {'initProgress': _progress},
creationParamsCodec: const StandardMessageCodec(),
),
),
const SizedBox(height: 30),
Text('当前进度:$_progress%', style: const TextStyle(fontSize: 18)),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _updateProgress,
child: const Text('增加进度'),
)
],
),
),
);
}
}
案例说明
- 原生端:通过实现
PlatformView接口,将鸿蒙原生RoundProgressBar封装为可被 Flutter 调用的视图,并注册到 Flutter 引擎。 - Flutter 端:使用
AndroidView加载原生组件,通过MethodChannel实现进度值的双向传递,点击按钮即可同步更新原生进度条的显示。 - 核心优势:无需重构 Flutter 页面,直接复用鸿蒙原生 UI 组件,保留系统级交互体验。
三、案例 2:鸿蒙 Flutter 自定义插件开发
对于需要在多个 Flutter 项目中复用的鸿蒙原生能力,最佳方式是封装为Flutter 插件。我们以开发一个鸿蒙系统信息获取插件为例,演示插件的完整开发流程。
步骤 1:创建 Flutter 插件项目
在终端执行以下命令,创建一个 Flutter 插件项目:
flutter create --template=plugin harmony_system_info
cd harmony_system_info
插件项目结构中,android目录替换为鸿蒙原生代码目录(harmony),用于存放鸿蒙原生实现。
步骤 2:鸿蒙原生端实现插件逻辑
在harmony > src > main > java > com > example > harmonysysteminfo目录下,创建HarmonySystemInfoPlugin.java,实现插件的核心功能(获取系统版本、设备型号):
package com.example.harmonysysteminfo;
import ohos.system.DeviceInfo;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;
public class HarmonySystemInfoPlugin implements MethodCallHandler {
private Registrar registrar;
public HarmonySystemInfoPlugin(Registrar registrar) {
this.registrar = registrar;
}
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "harmony_system_info");
channel.setMethodCallHandler(new HarmonySystemInfoPlugin(registrar));
}
@Override
public void onMethodCall(MethodCall call, Result result) {
switch (call.method) {
case "getSystemVersion":
// 获取鸿蒙系统版本
String version = DeviceInfo.getOsFullName();
result.success(version);
break;
case "getDeviceModel":
// 获取设备型号
String model = DeviceInfo.getDeviceModel();
result.success(model);
break;
default:
result.notImplemented();
break;
}
}
}
步骤 3:Flutter 端封装插件 API
在lib/harmony_system_info.dart中,封装插件的调用方法,供 Flutter 项目直接使用:、
import 'dart:async';
import 'package:flutter/services.dart';
class HarmonySystemInfo {
static const MethodChannel _channel = MethodChannel('harmony_system_info');
/// 获取鸿蒙系统版本号
static Future<String?> get systemVersion async {
final String? version = await _channel.invokeMethod('getSystemVersion');
return version;
}
/// 获取设备型号
static Future<String?> get deviceModel async {
final String? model = await _channel.invokeMethod('getDeviceModel');
return model;
}
}
步骤 4:在 Flutter 项目中使用插件
在 Flutter 项目的pubspec.yaml中添加插件依赖:
dependencies:
flutter:
sdk: flutter
harmony_system_info:
path: ../harmony_system_info # 插件本地路径
然后在 Flutter 页面中调用插件 API:
import 'package:flutter/material.dart';
import 'package:harmony_system_info/harmony_system_info.dart';
void main() {
runApp(const MyPluginApp());
}
class MyPluginApp extends StatelessWidget {
const MyPluginApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '鸿蒙Flutter插件实战',
theme: ThemeData(primarySwatch: Colors.blue),
home: const PluginTestPage(),
);
}
}
class PluginTestPage extends StatefulWidget {
const PluginTestPage({super.key});
@override
State<PluginTestPage> createState() => _PluginTestPageState();
}
class _PluginTestPageState extends State<PluginTestPage> {
String _systemVersion = '未知';
String _deviceModel = '未知';
@override
void initState() {
super.initState();
_getSystemInfo();
}
// 调用插件获取系统信息
Future<void> _getSystemInfo() async {
try {
final String? version = await HarmonySystemInfo.systemVersion;
final String? model = await HarmonySystemInfo.deviceModel;
setState(() {
_systemVersion = version ?? '获取失败';
_deviceModel = model ?? '获取失败';
});
} catch (e) {
setState(() {
_systemVersion = '获取异常:$e';
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('鸿蒙系统信息插件')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('鸿蒙系统版本:$_systemVersion', style: const TextStyle(fontSize: 16)),
const SizedBox(height: 10),
Text('设备型号:$_deviceModel', style: const TextStyle(fontSize: 16)),
],
),
),
);
}
}
案例说明
- 插件封装:将鸿蒙原生的
DeviceInfoAPI 封装为 Flutter 插件,实现了代码的复用性和可维护性。 - 调用方式:Flutter 项目通过简单的 API 调用,即可获取鸿蒙系统信息,无需关注原生端的实现细节。
- 扩展场景:此插件可进一步扩展,添加获取电池状态、网络信息等鸿蒙原生能力。
四、鸿蒙 Flutter 混合开发注意事项
- 版本兼容:确保 DevEco Studio、鸿蒙 SDK、Flutter SDK 的版本兼容,避免出现插件注册失败、视图渲染异常等问题。
- 性能优化:嵌入原生组件时,尽量减少视图层级嵌套,避免频繁的跨端通信导致性能损耗。
- 权限申请:调用鸿蒙系统级 API(如设备信息、相机)时,需在
config.json中声明对应权限。 - 调试技巧:使用 DevEco Studio 调试原生代码,使用 Flutter DevTools 调试 Flutter 代码,双端联调提高开发效率。
五、总结
鸿蒙 Flutter 混合开发是打通跨端开发与鸿蒙原生能力的关键技术,通过PlatformView实现原生组件嵌入、通过插件化开发实现能力复用,能够充分发挥 Flutter 的跨端优势和鸿蒙的系统级特性。本文的两个案例覆盖了混合开发的核心场景,开发者可根据实际业务需求,进一步探索方舟卡片、分布式任务等高级功能的混合开发方案。
随着鸿蒙生态的不断完善,Flutter 与鸿蒙的融合将更加深入,未来会有更多的原生能力和开发工具支持混合开发,为开发者带来更高效的开发体验
欢迎大家加入[开源鸿蒙跨平台开发者社区](https://openharmonycrossplatform.csdn.net),一起共建开源鸿蒙跨平台生态。
更多推荐



所有评论(0)