一、功能介绍

PlatformView是Flutter跨平台开发中的一项核心技术,它允许Flutter应用嵌入和使用原生平台的UI组件。在OpenHarmony平台上,PlatformView为Flutter开发者提供了访问鸿蒙原生能力的桥梁,实现了Flutter与OpenHarmony原生组件的无缝集成。

1.1 核心特性

  • 原生组件嵌入:在Flutter界面中直接使用OpenHarmony原生UI组件
  • 双向通信:支持Flutter与原生组件之间的消息传递
  • 生命周期管理:自动处理原生组件的创建、更新和销毁
  • 跨平台兼容:保持Flutter代码的跨平台特性,同时利用平台特定功能

1.2 技术依赖

  • OpenHarmony API 20及以上版本
  • Flutter SDK 3.27.5-ohos-1.0.0及以上版本
  • DevEco Studio 5.0.5+(用于OpenHarmony原生开发)

1.3 适用场景

  • 需要使用特定OpenHarmony原生UI组件的场景
  • 需要调用OpenHarmony平台特定API的功能
  • 性能敏感的原生组件(如地图、视频播放器等)
  • 已有的OpenHarmony原生组件需要复用的情况

二、环境准备

2.1 开发工具

  • DevEco Studio:版本5.0.5 Release及以上
    • 下载地址:https://developer.huawei.com/consumer/cn/download/deveco-studio
  • JDK:版本17
  • Node.js:版本16及以上

2.2 Flutter SDK

需要使用支持OpenHarmony PlatformView的Flutter SDK,具体要求:

  • 版本:3.27.5-ohos-1.0.0及以上
  • 分支:3.27.5-ohos-1.0.0
  • 获取地址:https://atomgit.com/openharmony-tpc/flutter_flutter/tree/3.27.5-ohos-1.0.0

2.3 环境变量配置

# Flutter环境变量
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
export PATH=/path/to/flutter_flutter/bin:$PATH

# OpenHarmony环境变量
export OHOS_HOME=/path/to/ohos/ohos-sdk

2.4 验证环境

配置完成后,执行以下命令验证环境:

# 验证Flutter版本
flutter --version

# 验证Flutter环境
flutter doctor -v

三、包的引入与配置

3.1 创建Flutter项目

使用以下命令创建支持OpenHarmony平台的Flutter项目:

flutter create --platforms ohos platform_demo
cd platform_demo
flutter pub get

3.2 项目结构

创建完成后,项目将包含以下主要目录:

  • lib/:Flutter Dart代码目录
  • ohos/:OpenHarmony原生代码目录
    • entry/src/main/ets/:OpenHarmony ArkTS代码

四、API调用和使用示例

4.1 原生侧实现(ArkTS)

4.1.1 创建自定义View组件

platform_demo/ohos/entry/src/main/ets/entryability目录下创建CustomView.ets文件:

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';

// 自定义组件,用于在Flutter中显示
@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)
          .onClick((event: ClickEvent) => {
            this.customView.sendMessage();
            console.log("OpenHarmony按钮被点击")
          })

        Text(`来自Flutter的数据 : ${this.storageLink}`)
      }
      .alignItems(HorizontalAlign.Center)
      .justifyContent(FlexAlign.Center)
      .width('100%')
      .height('100%')
    }
}

// Builder方法,用于构建自定义组件
@Builder
function ButtonBuilder(params: Params) {
  ButtonComponent({ params: params })
    .backgroundColor(Color.Yellow)
}

// 自定义PlatformView实现
@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("CustomView初始化,viewId:" + viewId)
        // 注册消息通道
        this.methodChannel = new MethodChannel(message, `com.rex.custom.ohos/customView${viewId}`, StandardMethodCodec.INSTANCE);
        this.methodChannel.setMethodCallHandler(this);
    }

    // 处理来自Flutter的方法调用
    onMethodCall(call: MethodCall, result: MethodResult): void {
        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("收到Flutter消息: " + this.numValue);
                result.success(true);
                break;
            default:
                result.notImplemented();
                break;
        }
    }

    // 向Flutter发送消息
    public sendMessage = () => {
        console.log("向Flutter发送消息")
        this.methodChannel.invokeMethod('getMessageFromOhosView', 'native - ' + this.index++);
    }

    // 返回自定义组件的Builder
    getView(): WrappedBuilder<[Params]> {
        return new WrappedBuilder(ButtonBuilder);
    }

    dispose(): void {
        // 清理资源
    }
}
4.1.2 创建PlatformView工厂

在同一目录下创建CustomFactory.ets文件:

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;
  }

  // 创建PlatformView实例
  public create(context: common.Context, viewId: number, args: Object): PlatformView {
    return new CustomView(context, viewId, args, this.message);
  }
}
4.1.3 创建Flutter插件

在同一目录下创建CustomPlugin.ets文件:

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';
  }

  // 插件初始化时注册PlatformView工厂
  onAttachedToEngine(binding: FlutterPluginBinding): void {
    binding.getPlatformViewRegistry()?.registerViewFactory('com.rex.custom.ohos/customView', new CustomFactory(binding.getBinaryMessenger(), StandardMessageCodec.INSTANCE));
  }

  onDetachedFromEngine(binding: FlutterPluginBinding): void {
    // 插件卸载时清理
  }
}
4.1.4 注册插件

修改EntryAbility.ets文件,注册自定义插件:

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()); // 注册自定义插件
  }
}

4.2 Flutter侧实现(Dart)

4.2.1 创建CustomOhosView组件

platform_demo/lib目录下创建custom_ohos_view.dart文件:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

typedef OnViewCreated = Function(CustomViewController);

/// 自定义OpenHarmony View组件
class CustomOhosView extends StatefulWidget {
  final OnViewCreated onViewCreated;

  const CustomOhosView(this.onViewCreated, {Key? key}) : super(key: key);

  
  State<CustomOhosView> createState() => _CustomOhosViewState();
}

class _CustomOhosViewState extends State<CustomOhosView> {
  late MethodChannel _channel;

  
  Widget build(BuildContext context) {
    return _getPlatformFaceView();
  }

  Widget _getPlatformFaceView() {
    return OhosView(
      viewType: 'com.rex.custom.ohos/customView', // 与原生侧注册的viewType一致
      onPlatformViewCreated: _onPlatformViewCreated,
      creationParams: const <String, dynamic>{'initParams': 'hello world'},
      creationParamsCodec: const StandardMessageCodec(),
    );
  }

  // PlatformView创建完成回调
  void _onPlatformViewCreated(int id) {
    _channel = MethodChannel('com.rex.custom.ohos/customView$id');
    final controller = CustomViewController._(
      _channel,
    );
    widget.onViewCreated(controller);
  }
}

/// CustomView控制器,用于与原生组件通信
class CustomViewController {
  final MethodChannel _channel;
  final StreamController<String> _controller = StreamController<String>();

  CustomViewController._(
    this._channel,
  ) {
    // 监听来自原生的消息
    _channel.setMethodCallHandler(
      (call) async {
        switch (call.method) {
          case 'getMessageFromOhosView':
            // 处理来自OpenHarmony的消息
            final result = call.arguments as String;
            _controller.sink.add(result);
            break;
        }
      },
    );
  }

  // 获取数据流
  Stream<String> get customDataStream => _controller.stream;

  // 向OpenHarmony发送消息
  Future<void> sendMessageToOhosView(String message) async {
    await _channel.invokeMethod(
      'getMessageFromFlutterView',
      message,
    );
  }
}
4.2.2 主应用实现

修改lib/main.dart文件,集成CustomOhosView:

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);

  
  Widget build(BuildContext context) {
    return const Scaffold(
      body: CustomExample(),
    );
  }
}

class CustomExample extends StatefulWidget {
  const CustomExample({Key? key}) : super(key: key);

  
  State<CustomExample> createState() => _CustomExampleState();
}

class _CustomExampleState extends State<CustomExample> {
  String receivedData = '';
  CustomViewController? _controller;

  // 自定义View创建完成回调
  void _onCustomOhosViewCreated(CustomViewController controller) {
    _controller = controller;
    // 监听来自原生的消息
    _controller?.customDataStream.listen((data) {
      setState(() {
        receivedData = '来自OpenHarmony的数据:$data';
      });
    });
  }

  // 构建OpenHarmony原生View
  Widget _buildOhosView() {
    return Expanded(
      child: Container(
        color: Colors.blueAccent.withAlpha(60),
        child: CustomOhosView(_onCustomOhosViewCreated),
      ),
      flex: 1,
    );
  }

  // 构建Flutter View
  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('发送数据给OpenHarmony'),
              ),
              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,
    );
  }

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        _buildOhosView(),
        _buildFlutterView(),
      ],
    );
  }
}

五、编译运行和验证方法

5.1 签名配置

  1. 使用DevEco Studio打开platform_demo/ohos项目
  2. 点击File > Project Structure > Project > Signing Configs
  3. 勾选Automatically generate signature,等待自动签名完成
  4. 点击OK保存配置

5.2 编译运行

  1. 连接OpenHarmony设备或启动模拟器
  2. 打开终端,进入项目目录
  3. 执行以下命令运行应用:
flutter run -d <device-id>

5.3 功能验证

应用运行后,可以进行以下验证:

  1. 界面布局

    • 上半部分为OpenHarmony原生组件(黄色背景)
    • 下半部分为Flutter组件(蓝色背景)
  2. 消息传递

    • 点击OpenHarmony端的"发送数据给Flutter"按钮,观察Flutter端是否显示收到的数据
    • 点击Flutter端的"发送数据给OpenHarmony"按钮,观察OpenHarmony端是否显示收到的数据
  3. 组件交互

    • 验证原生组件的点击事件是否正常响应
    • 验证Flutter与原生组件之间的通信是否流畅

六、常见问题与解决方案

6.1 PlatformView创建失败

问题:应用运行时出现"PlatformView creation failed"错误

解决方案

  • 确保viewType在Flutter侧和OpenHarmony侧完全一致
  • 检查OpenHarmony插件是否正确注册
  • 验证Flutter SDK版本是否支持PlatformView

6.2 消息通信失败

问题:Flutter与OpenHarmony之间的消息传递失败

解决方案

  • 检查MethodChannel的名称是否正确
  • 确保消息编解码器一致(使用StandardMessageCodec)
  • 检查方法名称是否匹配

6.3 组件显示异常

问题:PlatformView显示异常或不显示

解决方案

  • 确保CustomView正确实现了getView方法
  • 检查Builder方法是否正确构建组件
  • 验证组件尺寸设置是否合理

6.4 编译错误

问题:编译时出现"Undefined symbol"或"Class not found"错误

解决方案

  • 检查依赖导入路径是否正确
  • 确保所有必要的库都已正确引用
  • 验证Flutter和OpenHarmony SDK版本兼容性

七、总结

PlatformView是Flutter在OpenHarmony平台上实现原生组件集成的核心技术,它为开发者提供了访问原生能力的强大工具。通过本文的介绍,开发者可以了解到:

  1. PlatformView的核心概念:实现Flutter与OpenHarmony原生组件的无缝集成
  2. 完整的实现流程:从环境配置到代码实现的全流程指导
  3. 双向通信机制:Flutter与OpenHarmony之间的消息传递方法
  4. 实际应用示例:完整的代码示例展示了PlatformView的具体使用

合理使用PlatformView可以充分发挥Flutter的跨平台优势和OpenHarmony的原生能力,为用户提供更加丰富和高效的应用体验。

八、社区支持

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

在社区中,您可以获取最新的技术资讯、交流开发经验、解决技术问题,与其他开发者共同推动OpenHarmony跨平台生态的发展。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐