当前位置:   article > 正文

Flutter鸿蒙终端一体化—鹊桥相会

@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/flutterplugin' or i

3d45b50435c7f3cb1131597a01eecad8.png

点击上方蓝字关注我,知识会给你力量

c67c3f82763bd0b3d1dc8b2492f6fbd5.png

鸿蒙中开发Flutter项目,一个最大的问题,就是「不太会写鸿蒙代码」,这对于一个Flutter开发者来说,虽然不是一件很麻烦的事,但由于现在鸿蒙的版本和文档还略有一些混乱,所以要写好还是有一些麻烦的,所以,秉着能用工具解决的问题就不要自己写的原则,我们参考Native的Flutter Channel的实现,也就是pigeon的方式,不熟悉的同学可以参考我之前的文章。

Flutter混编工程之高速公路Pigeon

这套东西在鸿蒙中也有的适配,可以一键生成ets代码,方便我们进行多端复用,项目地址如下。

https://gitee.com/openharmony-sig/flutter_packages/tree/master/packages/pigeon

在鸿蒙中使用也非常简单,指定引用即可,代码如下所示。

  1. yaml
  2. pigeon:
  3. git:
  4. url: "https://gitee.com/openharmony-sig/flutter_packages.git"
  5. path: "packages/pigeon"

pub get之后,参考我们之前的实现,创建一个接口协议文件,这里就用之前的来示例。

  1. dart
  2. import 'package:pigeon/pigeon.dart';
  3. @HostApi()
  4. abstract class NativeNetApi {
  5. @async
  6. String getNativeNetBridge(String path, Map<String, Object> params);
  7. @async
  8. String postNativeNetBridge(String path, Map<String, Object> params);
  9. void doActionUrlCall(String actionUrl);
  10. }

接下来执行命令:

  1. shell
  2. flutter pub run pigeon --input lib/native_api.dart --arkts_out lib/native_channel.ets --dart_out lib/native_channel.dart

执行完成后,就会在指定目录下生成我们需要的Channel文件,dart代码我就不贴了,和之前文章中的一样,我们来看下鸿蒙的代码。

  1. arkts
  2. import StandardMessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec';
  3. import BasicMessageChannel, { Reply } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BasicMessageChannel';
  4. import { BinaryMessenger,TaskQueue } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger';
  5. import MessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/MessageCodec';
  6. import { ByteBuffer } from '@ohos/flutter_ohos/src/main/ets/util/ByteBuffer';
  7. /** Error class for passing custom error details to Flutter via a thrown PlatformException. */
  8. export class FlutterError implements Error {
  9. /** The error code. */
  10. public code: string;
  11. /** The error name. */
  12. public name: string;
  13. /** The error message. */
  14. public message: string;
  15. /** The error stack. */
  16. public stack?: string;
  17. constructor(code: string, name: string, message: string, stack: string)
  18. {
  19. this.code = code;
  20. this.name = name;
  21. this.message = message;
  22. this.stack = stack;
  23. }
  24. }
  25. function wrapError(error: Error): Array<Object> {
  26. let errorList: Array<Object> = new Array<Object>(3);
  27. if (error instanceof FlutterError) {
  28. let err: FlutterError = error as FlutterError;
  29. errorList[0] = err.code;
  30. errorList[1] = err.name;
  31. errorList[2] = err.message;
  32. } else {
  33. errorList[0] = error.toString();
  34. errorList[1] = error.name;
  35. errorList[2] = "Cause: " + error.message + ", Stacktrace: " + error.stack;
  36. }
  37. return errorList;
  38. }
  39. export interface Result<T> {
  40. success( result: T ): void;
  41. error( error: Error): void;
  42. }
  43. /* Generated abstract class from Pigeon that represents a handler of messages from Flutter.*/
  44. export abstract class NativeNetApi {
  45. abstract getNativeNetBridge(path: string , params: Map<string, Object> , result: Result<string>): void;
  46. abstract postNativeNetBridge(path: string , params: Map<string, Object> , result: Result<string>): void;
  47. abstract doActionUrlCall(actionUrl: string ): void;
  48. /** The codec used by NativeNetApi. */
  49. static getCodec(): MessageCodec<Object>{
  50. return new StandardMessageCodec();
  51. }
  52. /*Sets up an instance of `NativeNetApi` to handle messages through the `binaryMessenger`.*/
  53. static setup(binaryMessenger: BinaryMessenger, api: NativeNetApi | null): void {
  54. {
  55. let channel: BasicMessageChannel<Object> =
  56. new BasicMessageChannel(
  57. binaryMessenger, "dev.flutter.pigeon.test1.NativeNetApi.getNativeNetBridge", NativeNetApi.getCodec());
  58. if (api != null) {
  59. channel.setMessageHandler({
  60. onMessage(message: Object ,reply: Reply<Object> ) {
  61. let args: Array<Object> = message as Array<Object>;
  62. class ResultImp implements Result<string>{
  63. success(result: string): void {
  64. let res: Array<Object> = [];
  65. res.push(result);
  66. reply.reply(res);
  67. }
  68. error(error: Error): void {
  69. let wrappedError: Array<Object> = wrapError(error);
  70. reply.reply(wrappedError);
  71. }
  72. }
  73. let resultCallback: Result<string> = new ResultImp();
  74. api!.getNativeNetBridge(args[0] as string, args[1] as Map<string, Object>, resultCallback);
  75. } });
  76. } else {
  77. channel.setMessageHandler(null);
  78. }
  79. }
  80. {
  81. let channel: BasicMessageChannel<Object> =
  82. new BasicMessageChannel(
  83. binaryMessenger, "dev.flutter.pigeon.test1.NativeNetApi.postNativeNetBridge", NativeNetApi.getCodec());
  84. if (api != null) {
  85. channel.setMessageHandler({
  86. onMessage(message: Object ,reply: Reply<Object> ) {
  87. let args: Array<Object> = message as Array<Object>;
  88. class ResultImp implements Result<string>{
  89. success(result: string): void {
  90. let res: Array<Object> = [];
  91. res.push(result);
  92. reply.reply(res);
  93. }
  94. error(error: Error): void {
  95. let wrappedError: Array<Object> = wrapError(error);
  96. reply.reply(wrappedError);
  97. }
  98. }
  99. let resultCallback: Result<string> = new ResultImp();
  100. api!.postNativeNetBridge(args[0] as string, args[1] as Map<string, Object>, resultCallback);
  101. } });
  102. } else {
  103. channel.setMessageHandler(null);
  104. }
  105. }
  106. {
  107. let channel: BasicMessageChannel<Object> =
  108. new BasicMessageChannel(
  109. binaryMessenger, "dev.flutter.pigeon.test1.NativeNetApi.doActionUrlCall", NativeNetApi.getCodec());
  110. if (api != null) {
  111. channel.setMessageHandler({
  112. onMessage(message: Object ,reply: Reply<Object> ) {
  113. let args: Array<Object> = message as Array<Object>;
  114. let res: Array<Object> = [];
  115. try {
  116. api!.doActionUrlCall(args[0] as string);
  117. res.push(null);
  118. }
  119. catch (error) {
  120. let wrappedError: Array<Object> = wrapError(error);
  121. res = wrappedError;
  122. }
  123. reply.reply(res);
  124. } });
  125. } else {
  126. channel.setMessageHandler(null);
  127. }
  128. }
  129. }
  130. }

整体代码和Java的代码很类似,阅读基本没什么障碍,使用方式也和Native保持一致,通过调用setup方法,传入接口的实现即可,这里就不赘述了。

这样一来,我们的通信协议就打通了,Flutter的代码基本可以无损迁移,在鸿蒙侧,只需要根据协议实现对应的Channel接口即可,这样就完成了Android、iOS、鸿蒙的UI多端统一,Flutter & 鸿蒙,真香。

向大家推荐下我的网站 https://www.yuque.com/xuyisheng  点击原文一键直达

专注 Android-Kotlin-Flutter 欢迎大家访问

往期推荐

本文原创公众号:群英传,授权转载请联系微信(Tomcat_xu),授权后,请在原创发表24小时后转载。

< END >

作者:徐宜生

更文不易,点个“三连”支持一下

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/319693
推荐阅读
相关标签