HarmonyOS next之Flutter Ohos PlatformView得使用

一、创建项目

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

cd` 到 `platform_demo `目录下,执行 `flutter pub get`下载依赖

二、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/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';
    
    @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.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);
  }
}

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

import  { FlutterPlugin,
  FlutterPluginBinding } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin';
import StandardMessageCodec from '@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/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());
  }
}

三、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>

flfljh
1 声望1 粉丝