Flutter跨平台开发:Android View 在鸿蒙系统上的使用指南

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 视图

  1. 在鸿蒙应用的布局文件中添加 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>
  1. 在鸿蒙应用的 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 模块开发

  1. 在 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 与鸿蒙原生代码进行通信:

  1. 在 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}');
    }
  }
  
  // ...
}
  1. 在鸿蒙原生代码中注册 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 视图显示为空白或无法加载。

解决方案

  1. 检查 Flutter SDK 版本是否符合要求(2.19.5 或更高)
  2. 确保 Flutter 模块已正确构建(运行 flutter build aar
  3. 检查鸿蒙应用的 config.json 文件中是否已配置 Flutter 相关权限
  4. 查看日志获取详细错误信息:hdc shell logcat -s Flutter

6.2 原生插件无法正常工作

问题:Flutter 模块中使用的原生插件(如 url_launcher、sensors)在鸿蒙应用中无法正常工作。

解决方案

  1. 确保插件版本与 Flutter SDK 版本兼容
  2. 检查鸿蒙应用是否已添加必要的权限(如网络权限、传感器权限等)
  3. 对于自定义插件,需要确保已适配鸿蒙系统

6.3 性能问题

问题:嵌入 Flutter 视图后,鸿蒙应用的性能下降。

解决方案

  1. 避免在同一屏幕上嵌入过多 Flutter 视图
  2. 优化 Flutter 代码,减少不必要的重建和重绘
  3. 合理使用 Flutter 的异步加载和缓存机制
  4. 考虑使用 Flutter 的 release 模式构建应用(flutter build aar --release

7. 总结

Flutter Android View 提供了一种在鸿蒙应用中以视图级别集成 Flutter 模块的有效方式,它允许开发者逐步将 Flutter 功能引入现有鸿蒙应用,实现原生与 Flutter 的混合开发。

通过本文的指南,您已经了解了如何:

  • 在鸿蒙应用中嵌入 Flutter 视图
  • 配置和使用 Flutter 模块
  • 实现原生鸿蒙与 Flutter 之间的通信
  • 构建和运行混合应用

这种混合开发模式为开发者提供了更大的灵活性,可以根据项目需求选择最合适的技术栈,同时充分利用 Flutter 的跨平台能力和鸿蒙系统的原生优势。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

相关推荐
子一!!2 小时前
MySQL==表的结构操作1
android·python·adb
你不是我我2 小时前
【Java 开发日记】我们来说一下 MySQL 的慢查询日志
android·java·mysql
梦幻通灵11 小时前
Mysql字段判空实用技巧
android·数据库·mysql
盐焗西兰花11 小时前
鸿蒙学习实战之路-ArkTS循环渲染_ForEach使用指南
学习·华为·harmonyos
AiFlutter12 小时前
蓝牙助手APP开发(01):功能展示
flutter·低代码·低代码平台·aiflutter·aiflutter 低代码·蓝牙调试·蓝牙助手app
龘龍龙13 小时前
Python基础(九)
android·开发语言·python
gjc59214 小时前
MySQL隐蔽 BUG:组合条件查询无故返回空集?深度排查与规避方案
android·数据库·mysql·bug
俩毛豆14 小时前
【鸿蒙生态共建】意图框架的使用-通过小艺调起京东发起搜索《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》读者福利
华为·harmonyos·小艺
梨落秋霜14 小时前
Python入门篇【元组】
android·数据库·python