Flutter鸿蒙下原生视图的使用说明

一、背景介绍     

在跨平台开发中,Flutter 通过 PlatformView 机制允许开发者嵌入原生平台的视图组件。对于鸿蒙(HarmonyOS)系统,同样可以通过类似机制实现 Flutter 与原生组件的无缝整合。本文将介绍如何在 Flutter 应用中嵌入鸿蒙原生视图,并实现双向通信。

二、 PlatformView 机制

Flutter 通过 PlatformView 接口将原生视图渲染到 Flutter 的 widget 树中。对于鸿蒙系统,我们需要:

1、创建鸿蒙原生组件:使用 Java/JS 编写 HarmonyOS 的 UI 组件。

2、建立通信桥梁:通过 MethodChannel 实现 Flutter 与原生端的双向通信。

2、处理布局与生命周期:协调 Flutter 与原生视图的布局和渲染。


三、实现步骤

1、创建 Flutter 插件项目:

flutter create --template=plugin harmony_view

2、鸿蒙原生端实现

   使用 DevEco Studio工具打开 harmony_view\ohos项目,在harmony_view\ohos\entry\src\main\ets\entryability目录下实现代码

2.1、新建CustomView.ets文件,CustomView用于在Flutter Widget里显示

    @Componentstruct ButtonComponent {    @Prop params: Params    customView: CustomView = this.params.platformView as CustomView    @StorageLink('numValue') storageLink: string = "first"    @State bkColor: Color = Color.Red
        build() {      Column() {        Button("发送数据给Flutter")          .border({ width: 2, color: Color.Blue})          .backgroundColor(this.bkColor)          .onTouch((event: TouchEvent) => {            console.log("nodeController button on touched")          })          .onClick((event: ClickEvent) => {            this.customView.sendMessage();            console.log("nodeController button on click")           })
            Text(`来自Flutter的数据 : ${this.storageLink}`)          .onTouch((event: TouchEvent) => {            console.log("nodeController text on touched")          })
            }.alignItems(HorizontalAlign.Center)         .justifyContent(FlexAlign.Center)         .direction(Direction.Ltr)         .width('100%')         .height('100%')    }}

    2.2、定义一个builder方法,放入2.1的自定义Component组件

    @Builderfunction ButtonBuilder(params: Params) {   ButtonComponent({ params: params })     .backgroundColor(Color.Yellow)}

    2.3、继承PlatformView实现一个自定义的Customview,实现getView接口,返回WrappedBuilder(ButtonBuilder),放入2.2的的builder方法

    import MethodChannel, {        MethodCallHandler,        MethodResult        } from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel';import PlatformView, { Params } from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView';import common from '@ohos.app.ability.common';import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger';import StandardMethodCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMethodCodec';import MethodCall from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall';
    @Observedexport class CustomView extends PlatformView implements MethodCallHandler {    numValue: string = "test";
        methodChannel: MethodChannel;    index: number = 1;
        constructor(context: common.Context, viewId: number, args: ESObject, message: BinaryMessenger) {        super();        console.log("nodeController viewId:" + viewId)        // 注册消息通道,消息通道根据具体需求添加,代码仅作为示例        this.methodChannel = new MethodChannel(message, `com.rex.custom.ohos/customView${viewId}`, StandardMethodCodec.INSTANCE);        this.methodChannel.setMethodCallHandler(this);    }
        onMethodCall(call: MethodCall, result: MethodResult): void {        // 接受Dart侧发来的消息        let method: string = call.method;        let link1: SubscribedAbstractProperty<number> = AppStorage.link('numValue');        switch (method) {            case 'getMessageFromFlutterView':                let value: ESObject = call.args;                this.numValue = value;                link1.set(value)                console.log("nodeController receive message from dart: " + this.numValue);                result.success(true);                break;        }    }
        public sendMessage = () => {        console.log("nodeController sendMessage")        //向Dart侧发送消息        this.methodChannel.invokeMethod('getMessageFromOhosView', 'natvie - ' + this.index++);    }
        getView(): WrappedBuilder<[Params]> {        return new WrappedBuilder(ButtonBuilder);    }
        dispose(): void {    }}

    2.4、实现一个自定义的PlatformViewFactory,在其create方法中创建自定义的PlatformView的实例

    import common from '@ohos.app.ability.common';import MessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/MessageCodec';import PlatformViewFactory from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewFactory';import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger';import PlatformView from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView';import { CustomView } from './CustomView';
    export class CustomFactory extends PlatformViewFactory {  message: BinaryMessenger;
      constructor(message: BinaryMessenger, createArgsCodes: MessageCodec<Object>) {    super(createArgsCodes);    this.message = message;  }
      public create(context: common.Context, viewId: number, args: Object): PlatformView {    return new CustomView(context, viewId, args, this.message);  }}

    1.5、新建一个继承于FlutterPlugin的CustomPlugin插件,在onAttachedToEngine中,注册自定义的PlatformViewFactory

    import { FlutterAbility } from '@ohos/flutter_ohos'
    import FlutterEngine from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngine';
    import { CustomPlugin } from './CustomPlugin';
    import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant';
    
    export default class EntryAbility extends FlutterAbility {
      configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        GeneratedPluginRegistrant.registerWith(flutterEngine)
        this.addPlugin(new CustomPlugin());
      }
    }
    

    3、Flutter 端实现

      用AndroidStudio工具打开harmony_view项目在harmony_view\lib目录下实现代码,新建CustomOhosView.dart,用于显示Native侧的CustomView的Widget OhosView组件就是桥接PlatformView的关键。

    • viewType:传递给Native侧,告知插件需要创建那个PlatformView,这个PlatformView需要在插件初始化时注册。

    • onPlatformViewCreated:PlatformView创建成功时的回调。

    • creationParams:传递给PlatformView的初始化参数。

    3.1、实现CustomOhosView,使用OhosView组件,viewType需要和ets侧FlutterPluginregisterViewFactory操作时指定的viewType一致

    import 'dart:async'; import 'package:flutter/material.dart';import 'package:flutter/services.dart'; typedef OnViewCreated = Function(CustomViewController); ///自定义OhosViewclass CustomOhosView extends StatefulWidget { final OnViewCreated onViewCreated; const CustomOhosView(this.onViewCreated, {Key? key}) : super(key: key); @override State<CustomOhosView> createState() => _CustomOhosViewState();} class _CustomOhosViewState extends State<CustomOhosView> { late MethodChannel _channel; @override Widget build(BuildContext context) { return _getPlatformFaceView(); } Widget _getPlatformFaceView() { return OhosView( viewType: 'com.rex.custom.ohos/customView', onPlatformViewCreated: _onPlatformViewCreated, creationParams: const <String, dynamic>{'initParams': 'hello world'}, creationParamsCodec: const StandardMessageCodec(), ); } void _onPlatformViewCreated(int id) { _channel = MethodChannel('com.rex.custom.ohos/customView$id'); final controller = CustomViewController._( _channel, ); widget.onViewCreated(controller); }}

    3.2、在CustomOhosView所在文件中新建CustomViewController,用于实现Dart侧与Native侧的交互

    class CustomViewController {  final MethodChannel _channel;  final StreamController<String> _controller = StreamController<String>();
      CustomViewController._(    this._channel,  ) {    _channel.setMethodCallHandler(      (call) async {        switch (call.method) {          case 'getMessageFromOhosView':            // 从native端获取数据            final result = call.arguments as String;            _controller.sink.add(result);            break;        }      },    );  }
      Stream<String> get customDataStream => _controller.stream;
      // 发送数据给native  Future<void> sendMessageToOhosView(String message) async {    await _channel.invokeMethod(      'getMessageFromFlutterView',      message,    );  }}

    3.3、修改harmony_view\lib\main.dart文件中的代码写测试

    import 'dart:math';
    import 'package:flutter/material.dart';import 'custom_ohos_view.dart';
    void main() {  runApp(const MaterialApp(home: MyHome()));}
    class MyHome extends StatelessWidget {  const MyHome({Key? key}) : super(key: key);
      @override  Widget build(BuildContext context) {    return const Scaffold(      body: CustomExample(),    );  }}
    class CustomExample extends StatefulWidget {  const CustomExample({Key? key}) : super(key: key);
      @override  State<CustomExample> createState() => _CustomExampleState();}
    class _CustomExampleState extends State<CustomExample> {  String receivedData = '';  CustomViewController? _controller;
      void _onCustomOhosViewCreated(CustomViewController controller) {    _controller = controller;    _controller?.customDataStream.listen((data) {      //接收到来自OHOS端的数据      setState(() {        receivedData = '来自ohos的数据:$data';      });    });  }
      Widget _buildOhosView() {    return Expanded(      child: Container(        color: Colors.blueAccent.withAlpha(60),        child: CustomOhosView(_onCustomOhosViewCreated),      ),      flex: 1,    );  }
      Widget _buildFlutterView() {    return Expanded(      child: Stack(        alignment: AlignmentDirectional.bottomCenter,        children: [          Column(            mainAxisAlignment: MainAxisAlignment.center,            mainAxisSize: MainAxisSize.max,            children: [              TextButton(                onPressed: () {                  final randomNum = Random().nextInt(10);                  _controller                      ?.sendMessageToOhosView('flutter - $randomNum ');                },                child: const Text('发送数据给ohos'),              ),              const SizedBox(height: 10),              Text(receivedData),            ],          ),          const Padding(            padding: EdgeInsets.only(bottom: 15),            child: Text(              'Flutter - View',              style: TextStyle(                fontSize: 20,                fontWeight: FontWeight.bold,              ),            ),          ),        ],      ),      flex: 1,    );  }
      @override  Widget build(BuildContext context) {    return Column(      children: [        _buildOhosView(),        _buildFlutterView(),      ],    );  }}


    四、总结

    通过 PlatformView 集成鸿蒙原生视图,开发者可以:

    • 保留 Flutter 跨平台优势

    • 充分利用鸿蒙系统特性

    • 实现渐进式混合开发

    未来随着 HarmonyOS 生态的发展,这种混合开发模式将显著提升应用的功能扩展能力。

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值