精华 Flutter使用platformview 加载HarmonyOS页面实现Flutter和HarmonyOS的混合开发

发布于 1周前 作者 itying888 最后一次编辑是 5天前 来自 分享

Flutter使用platformview 加载HarmonyOS页面实现Flutter和HarmonyOS的混合开发

在Flutter中,通过PlatformView可以实现与原生平台(如iOS和Android)的交互。对于HarmonyOS(鸿蒙系统),虽然Flutter官方尚未直接提供对HarmonyOS的原生视图支持,但你可以通过一些自定义的桥接方式来实现Flutter与HarmonyOS的混合开发。

Flutter Ohos PlatformView得使用

一、创建项目

执行`flutter create --platforms ohos platform_demo`创建项目

cdplatform_demo 目录下,执行flutter pub get`下载依赖

二、HarmonyOS ohos端

  1. 使用 DevEco Studio工具打开 platform_demo\ohos项目

  2. platform_demo\ohos\entry\src\main\ets\entryability目录下实现代码

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

3.1 定义一个Component,代表ohos的PlatformView的定义

@Component
struct 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%')
}

}

3.2 定义一个builder方法,放入3.1的自定义Component组件

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

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

import MethodChannel, {
        MethodCallHandler,
        MethodResult
        } from '[@ohos](/user/ohos)/flutter_ohos/src/main/ets/plugin/common/MethodChannel';
import PlatformView, { Params } from '[@ohos](/user/ohos)/flutter_ohos/src/main/ets/plugin/platform/PlatformView';
import common from '[@ohos](/user/ohos).app.ability.common';
import { BinaryMessenger } from '[@ohos](/user/ohos)/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger';
import StandardMethodCodec from '[@ohos](/user/ohos)/flutter_ohos/src/main/ets/plugin/common/StandardMethodCodec';
import MethodCall from '[@ohos](/user/ohos)/flutter_ohos/src/main/ets/plugin/common/MethodCall';

@Observed export 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 {
}

}

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

import common from '[@ohos](/user/ohos).app.ability.common';
import MessageCodec from '[@ohos](/user/ohos)/flutter_ohos/src/main/ets/plugin/common/MessageCodec';
import PlatformViewFactory from '[@ohos](/user/ohos)/flutter_ohos/src/main/ets/plugin/platform/PlatformViewFactory';
import { BinaryMessenger } from '[@ohos](/user/ohos)/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger';
import PlatformView from '[@ohos](/user/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); } }

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

import  { FlutterPlugin,
  FlutterPluginBinding } from '[@ohos](/user/ohos)/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin';
import StandardMessageCodec from '[@ohos](/user/ohos)/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec';
import { CustomFactory } from './CustomFactory';

export class CustomPlugin implements FlutterPlugin { getUniqueClassName(): string { return ‘CustomPlugin’; }

onAttachedToEngine(binding: FlutterPluginBinding): void { binding.getPlatformViewRegistry()?. registerViewFactory(‘com.rex.custom.ohos/customView’, new CustomFactory(binding.getBinaryMessenger(), StandardMessageCodec.INSTANCE)); }

onDetachedFromEngine(binding: FlutterPluginBinding): void {} }

3.6 打开EntryAbility.ets文件,添加Plugin(也可以把自定义PlatformView写在一个鸿蒙插件中,在应用中沿用,就不用在此显式添加插件)

import { FlutterAbility } from '[@ohos](/user/ohos)/flutter_ohos'
import FlutterEngine from '[@ohos](/user/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()); } }

三、flutter 端

  1. 使用 Android Studio工具打开 platform_demo项目

  2. platform_demo\lib目录下实现代码

  3. 新建CustomOhosView,用于显示Native侧的CustomView的Widget
    OhosView组件就是桥接PlatformView的关键。

  • viewType:传递给Native侧,告知插件需要创建那个PlatformView,这个PlatformView需要在插件初始化时注册。
  • onPlatformViewCreated:PlatformView创建成功时的回调。
  • creationParams:传递给PlatformView的初始化参数。

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

import 'dart:async';

import ‘package:flutter/material.dart’; import ‘package:flutter/services.dart’;

typedef OnViewCreated = Function(CustomViewController);

///自定义OhosView class 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); } }

  1. 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, ); } }

  1. 修改platform_demo\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(), ], ); } }

编译运行

一、签名

  1. 使用 DevEco Studio工具打开 platform_demo\ohos目录

  2. 单击 File > Project Structure > Project > Signing Configs界面勾选 Automatically generate signature,等待自动签名完成,点击OK

二、编译运行

  1. cdplatform_demo 目录下

  2. 打开 终端,执行下面指令进行编译运行:

flutter run -d <device-id>

更多关于Flutter使用platformview 加载HarmonyOS页面实现Flutter和HarmonyOS的混合开发的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter使用platformview 加载HarmonyOS页面实现Flutter和HarmonyOS的混合开发的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


Flutter与HarmonyOS(Ohos)PlatformView交互的主要步骤

以下是基于《Flutter Ohos PlatformView得使用》一文整理的使用Flutter进行HarmonyOS(Ohos)混合开发时,通过PlatformView实现Flutter与HarmonyOS原生页面交互的主要步骤,内容以Markdown格式输出:

一、创建项目

  1. 执行以下命令创建Flutter项目,并指定平台为HarmonyOS:
    flutter create --platforms ohos platform_demo
    
  2. 进入platform_demo目录,执行以下命令下载依赖:
    flutter pub get
    

二、HarmonyOS端开发

  1. 使用DevEco Studio工具打开platform_demo\ohos项目。

  2. platform_demo\ohos\entry\src\main\ets\entryability目录下实现代码。

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

      • 定义一个Component,代表HarmonyOS的PlatformView的定义。

        • 创建一个Button,并为其添加点击和触摸事件监听。
        • 添加一个Text用于显示来自Flutter的数据。
      • 定义一个builder方法,用于放入自定义Component组件。

      • 继承PlatformView实现一个自定义的CustomView,实现getView接口,返回WrappedBuilder(ButtonBuilder),放入上一步定义的builder方法。

        • CustomView类中,注册消息通道,用于接收和发送来自Flutter的消息。
        • 实现onMethodCall方法,用于处理来自Flutter的消息。
        • 定义一个sendMessage方法,用于向Flutter发送消息。
    • 实现一个自定义的PlatformViewFactory,在其create方法中创建自定义的PlatformView的实例。

    • 新建一个继承于FlutterPluginCustomPlugin插件,在onAttachedToEngine中,注册自定义的PlatformViewFactory

    • 打开EntryAbility.ets文件,添加CustomPlugin插件。

三、Flutter端开发

  1. 使用Android Studio工具打开platform_demo项目。

  2. platform_demo\lib目录下实现代码。

    • 新建CustomOhosView,用于显示Native侧的CustomView的Widget。OhosView组件是桥接PlatformView的关键。

      • viewType:传递给Native侧,告知插件需要创建哪个PlatformView,这个PlatformView需要在插件初始化时注册。
      • onPlatformViewCreatedPlatformView创建成功时的回调。
      • creationParams:传递给PlatformView的初始化参数。
    • CustomOhosView所在文件中新建CustomViewController,用于实现Dart侧与Native侧的交互。

      • 监听来自Native侧的消息,并通过Stream发出。
      • 提供一个方法,用于发送消息给Native侧。
    • 修改platform_demo\lib\main.dart文件中的代码,将CustomOhosView和Flutter的UI结合使用。

      • 创建一个按钮,点击时发送消息给HarmonyOS端。
      • 显示接收到的来自HarmonyOS端的数据。

四、编译运行

  1. 使用DevEco Studio工具打开platform_demo\ohos目录进行签名。

  2. 编译运行:

    • cdplatform_demo目录下。
    • 打开终端,执行以下命令进行编译运行:
      flutter run -d <device-id>
      

通过以上步骤,可以实现Flutter与HarmonyOS原生页面的交互。

回到顶部