1. 插件介绍
Flutter Android View 是一个用于在 Android 应用中以视图级别集成 Flutter 模块的示例项目。它展示了如何将 Flutter 组件作为原生 Android 视图嵌入到现有应用中,实现 Flutter 与原生代码的无缝交互和混合开发。
这个示例项目特别适合以下场景:
- 需要在现有鸿蒙应用中逐步引入 Flutter 功能
- 希望在同一屏幕上同时展示原生鸿蒙 UI 和 Flutter UI
- 想利用 Flutter 的跨平台能力,同时保留现有鸿蒙应用的核心功能
2. 插件功能特性
- 支持在鸿蒙应用中以视图级别嵌入 Flutter 组件
- 实现原生鸿蒙与 Flutter 之间的双向通信
- 支持 Flutter 模块使用原生插件(如 url_launcher、sensors 等)
- 提供了完整的示例代码,包括列表展示和交互功能
- 支持热重载,提高开发效率
3. 快速开始
3.1 环境要求
- Flutter SDK 2.19.5 或更高版本
- HarmonyOS SDK 3.0 或更高版本
- DevEco Studio 3.0 或更高版本
- JDK 11 或更高版本
3.2 引入依赖
由于这是一个自定义修改版本的三方库,需要通过 Git 形式引入。在项目的 pubspec.yaml 文件中添加以下配置:
yaml
dependencies:
flutter:
sdk: flutter
flutter_module_using_plugin:
git:
url: "https://atomgit.com/flutter/samples.git"
path: "add_to_app/android_view/flutter_module_using_plugin"
provider: ^6.0.2
url_launcher: ^6.0.6
sensors: ^2.0.3
然后运行以下命令获取依赖:
bash
flutter pub get
4. 使用方法
4.1 鸿蒙应用中嵌入 Flutter 视图
- 在鸿蒙应用的布局文件中添加 Flutter 视图容器:
xml
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:orientation="vertical">
<!-- 鸿蒙原生 UI 组件 -->
<Text
ohos:height="60vp"
ohos:width="match_parent"
ohos:text="鸿蒙原生标题栏"
ohos:text_size="20fp"
ohos:text_alignment="center"
ohos:background_element="#FF007AFF"/>
<!-- Flutter 视图容器 -->
<ComponentContainer
ohos:id="$+id:flutter_container"
ohos:height="match_parent"
ohos:width="match_parent"/>
</DirectionalLayout>
- 在鸿蒙应用的 AbilitySlice 中初始化并加载 Flutter 视图:
java
import com.huawei.flutter.hmos.adapter.FlutterView;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.ComponentContainer;
public class MainAbilitySlice extends AbilitySlice {
private FlutterView flutterView;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
// 获取 Flutter 视图容器
ComponentContainer flutterContainer = (ComponentContainer) findComponentById(ResourceTable.Id_flutter_container);
// 初始化 Flutter 视图
flutterView = new FlutterView(getContext());
flutterView.setBundleName("dev.flutter.example.flutter_module_using_plugin");
flutterView.setEntrypoint("main");
// 将 Flutter 视图添加到容器中
flutterContainer.addComponent(flutterView);
// 启动 Flutter 引擎
flutterView.initialize();
}
@Override
protected void onForeground(Intent intent) {
super.onForeground(intent);
if (flutterView != null) {
flutterView.onForeground();
}
}
@Override
protected void onBackground() {
super.onBackground();
if (flutterView != null) {
flutterView.onBackground();
}
}
@Override
protected void onStop() {
super.onStop();
if (flutterView != null) {
flutterView.onStop();
}
}
}
4.2 Flutter 模块开发
- 在 Flutter 模块中创建 UI 组件:
dart
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:sensors/sensors.dart';
class FlutterAndroidViewExample extends StatefulWidget {
@override
_FlutterAndroidViewExampleState createState() => _FlutterAndroidViewExampleState();
}
class _FlutterAndroidViewExampleState extends State<FlutterAndroidViewExample> {
List<double> _accelerometerValues;
List<double> _userAccelerometerValues;
List<double> _gyroscopeValues;
final _streamSubscriptions = <StreamSubscription<dynamic>>[];
@override
void initState() {
super.initState();
_streamSubscriptions.add(
accelerometerEvents.listen(
(AccelerometerEvent event) {
setState(() {
_accelerometerValues = <double>[event.x, event.y, event.z];
});
},
),
);
_streamSubscriptions.add(
userAccelerometerEvents.listen(
(UserAccelerometerEvent event) {
setState(() {
_userAccelerometerValues = <double>[event.x, event.y, event.z];
});
},
),
);
_streamSubscriptions.add(
gyroscopeEvents.listen(
(GyroscopeEvent event) {
setState(() {
_gyroscopeValues = <double>[event.x, event.y, event.z];
});
},
),
);
}
@override
void dispose() {
super.dispose();
for (final subscription in _streamSubscriptions) {
subscription.cancel();
}
}
@override
Widget build(BuildContext context) {
final accelerometer = _accelerometerValues != null
? _accelerometerValues.map((double v) => v.toStringAsFixed(1)).toList()
: <String>['0.0', '0.0', '0.0'];
final userAccelerometer = _userAccelerometerValues != null
? _userAccelerometerValues.map((double v) => v.toStringAsFixed(1)).toList()
: <String>['0.0', '0.0', '0.0'];
final gyroscope = _gyroscopeValues != null
? _gyroscopeValues.map((double v) => v.toStringAsFixed(1)).toList()
: <String>['0.0', '0.0', '0.0'];
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Android View Example'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'Accelerometer: $accelerometer',
style: TextStyle(fontSize: 16.0),
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'User Accelerometer: $userAccelerometer',
style: TextStyle(fontSize: 16.0),
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'Gyroscope: $gyroscope',
style: TextStyle(fontSize: 16.0),
),
),
],
),
ElevatedButton(
child: const Text('Open Flutter Website'),
onPressed: () {
launch('https://flutter.dev');
},
),
],
),
),
);
}
}
4.3 原生与 Flutter 之间的通信
Flutter 模块可以通过 MethodChannel 与鸿蒙原生代码进行通信:
- 在 Flutter 模块中设置 MethodChannel:
dart
import 'package:flutter/services.dart';
class _FlutterAndroidViewExampleState extends State<FlutterAndroidViewExample> {
static const platform = MethodChannel('dev.flutter.example/channel');
Future<void> _callNativeMethod() async {
try {
final String result = await platform.invokeMethod('nativeMethod');
print('Native method result: $result');
} on PlatformException catch (e) {
print('Failed to call native method: ${e.message}');
}
}
// ...
}
- 在鸿蒙原生代码中注册 MethodChannel:
java
import com.huawei.flutter.hmos.adapter.MethodChannel;
import com.huawei.flutter.hmos.adapter.MethodCallHandler;
import com.huawei.flutter.hmos.adapter.MethodCall;
import com.huawei.flutter.hmos.adapter.Result;
public class MainAbilitySlice extends AbilitySlice {
private FlutterView flutterView;
@Override
public void onStart(Intent intent) {
// ... 初始化 FlutterView 代码 ...
// 注册 MethodChannel
new MethodChannel(flutterView.getFlutterEngine().getDartExecutor().getBinaryMessenger(), "dev.flutter.example/channel")
.setMethodCallHandler(new MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("nativeMethod")) {
String response = "Hello from HarmonyOS native code!";
result.success(response);
} else {
result.notImplemented();
}
}
});
}
// ...
}
5. 构建与运行
5.1 构建 Flutter 模块
在 Flutter 模块目录下运行以下命令构建 Flutter AAR:
bash
flutter build aar --no-debug --no-profile
5.2 构建鸿蒙应用
在 DevEco Studio 中打开鸿蒙应用项目,然后点击 "Build" -> "Build HAP(s)/APP(s)" -> "Build APP(s)" 构建完整的鸿蒙应用。
5.3 运行应用
将鸿蒙设备连接到开发机,然后在 DevEco Studio 中点击 "Run" 按钮或使用以下命令运行应用:
bash
hap build install
6. 常见问题与解决方案
6.1 Flutter 视图无法加载
问题:鸿蒙应用中 Flutter 视图显示为空白或无法加载。
解决方案:
- 检查 Flutter SDK 版本是否符合要求(2.19.5 或更高)
- 确保 Flutter 模块已正确构建(运行
flutter build aar) - 检查鸿蒙应用的
config.json文件中是否已配置 Flutter 相关权限 - 查看日志获取详细错误信息:
hdc shell logcat -s Flutter
6.2 原生插件无法正常工作
问题:Flutter 模块中使用的原生插件(如 url_launcher、sensors)在鸿蒙应用中无法正常工作。
解决方案:
- 确保插件版本与 Flutter SDK 版本兼容
- 检查鸿蒙应用是否已添加必要的权限(如网络权限、传感器权限等)
- 对于自定义插件,需要确保已适配鸿蒙系统
6.3 性能问题
问题:嵌入 Flutter 视图后,鸿蒙应用的性能下降。
解决方案:
- 避免在同一屏幕上嵌入过多 Flutter 视图
- 优化 Flutter 代码,减少不必要的重建和重绘
- 合理使用 Flutter 的异步加载和缓存机制
- 考虑使用 Flutter 的 release 模式构建应用(
flutter build aar --release)
7. 总结
Flutter Android View 提供了一种在鸿蒙应用中以视图级别集成 Flutter 模块的有效方式,它允许开发者逐步将 Flutter 功能引入现有鸿蒙应用,实现原生与 Flutter 的混合开发。
通过本文的指南,您已经了解了如何:
- 在鸿蒙应用中嵌入 Flutter 视图
- 配置和使用 Flutter 模块
- 实现原生鸿蒙与 Flutter 之间的通信
- 构建和运行混合应用
这种混合开发模式为开发者提供了更大的灵活性,可以根据项目需求选择最合适的技术栈,同时充分利用 Flutter 的跨平台能力和鸿蒙系统的原生优势。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net