22.原生项目和Flutter的混合开发(三)

目录传送门:《Flutter快速上手指南》先导篇java

经过阅读 混合开发(一)混合开发(二) ,相信你已经让一个 原生 + Flutetr 的混合应用运行起来了。git

恭喜你 🎉🎉🎉!github

如今,你可能遇到了 Flutter代码 和 原生代码 以前没法互相调用的难题。bash

由于 Flutter 做为独立于原生 Android 的一套开发框架,确定是不能直接互相调用和愉快的交换信息的。架构

如今,来看看 Flutter 是如何解决这些问题的。框架

1.Platform Channels

Flutter 使用 Platform Channels 架构来实现 Flutter 和 原生 之间的通讯。异步

上图是其中 MethodChannel 的架构示意图,Flutter 能够经过 MethodChannel 异步的发送和接收信息。async

MethodChannel 是通过封装的比较方便的通讯方式,Flutter 官网的例子也是经过 MethodChannel 来实现的。ide

Platform Channels 仅容许如下几种的数据类型在通讯中使用:函数

Dart Android iOS
null null nil (NSNull when nested)
bool java.lang.Boolean NSNumber numberWithBool
int java.lang.Integer NSNumber numberWithInt
int, if 32 bits not enough java.lang.Long NSNumber numberWithLong
double java.lang.Double NSNumber numberWithDouble
String java.lang.String NSString
Uint8List byte[] FlutterStandardTypedData typedDataWithBytes
Int32List int[] FlutterStandardTypedData typedDataWithInt32
Int64List long[] FlutterStandardTypedData typedDataWithInt64
Float64List double[] FlutterStandardTypedData typedDataWithFloat64
List java.util.ArrayList NSArray
Map java.util.HashMap NSDictionary

2.如何使用 MethodChannel

MethodChannel 经过特定的通道,来创建起 Flutter 和 Native 之间通讯桥梁。

固然,咱们须要在 Flutter 和 Native 两端都须要定义相同的通道。

2.1 第一步:定义通讯通道

  • Flutter 端:

    先导入 import 'package:flutter/services.dart'; 包,而后建立一个 MethodChannel。

    const channel = MethodChannel('foo');
    复制代码
  • Native - Android 端:

    MethodChannel channel = new MethodChannel(flutterView, "foo");复制代码
  • Native - iOS 端:

    let channel = FlutterMethodChannel(
      name: "foo", binaryMessenger: flutterView)
    复制代码

创建一个通讯通道的方式很简单,只须要使用相同的名称(好比上面例子中的 "foo")建立 MethodChannel 就行。

在一个大型的项目中。你可能会须要创建不少的通讯通道,因此建议统一的管理这些通讯通道。

2.2 Flutter to Native

创建好通讯通道,来看看如何让 Flutter 主动和 Native 通讯。

  • Flutter 端:

    final String greeting = await channel.invokeMethod('bar', 'world');
    print(greeting);复制代码

    经过 invokeMethod(<标识>, <数据>) 函数能够主动发起和 Native 的一次通讯,且可以得到响应,容许的数据类型就是前面表格中列出的数据类型。

    固然,为了避免阻塞 UI,你须要在异步中进行。

  • Native - Android 端:

    channel.setMethodCallHandler((methodCall, result) -> {
        if (methodCall.method.equals("bar")) {
            result.success("success, " + methodCall.arguments);
        }
    });复制代码

    在 Native 端,经过为 MethodChannel 设置一个处理器 MethodCallHandler

    当 Flutter 向 Native 发起通讯时,可以回调处理器中的 onMethodCall() 函数。

    在该回调中,可以经过 MethodCall 获取 Flutter 发送过来的信息,经过 MethodChannel.Result 来向 Flutter 发送响应结果。

  • Native - iOS 端:

    channel.setMethodCallHandler {
      (call: FlutterMethodCall, result: FlutterResult) -> Void in
      switch (call.method) {
      case "bar": result("Hello, \(call.arguments as! String)")
      default: result(FlutterMethodNotImplemented)
      }
    }
    复制代码

2.3 Native to Flutter

  • Flutter 端:

    设置接收 Native 信息的处理器:

    channel.setMethodCallHandler((MethodCall call) async {
      switch (call.method) {
        case 'bar':
          return 'Hello, ${call.arguments}';
        case 'baz':
          throw PlatformException(code: '400', message: 'This is bad');
        default:
          throw MissingPluginException();
      }
    })
    复制代码

    经过 setMethodCallHandler 函数设置一个 Future<dynamic> handler(MethodCall call) 函数。

    该函数会在接收到 Native 信息时被调用,从 MethodCall 中可以得到 Native 发送过来的数据。

    最后的 return 环节能够返回数据给 Native。

  • Native - Android 端:

    channel.invokeMethod("bar", "message", new MethodChannel.Result
        @Override
        public void success(@Nullable Object o) {
            // 发送成功时回调
        }
        @Override
        public void error(String s, @Nullable String s1, @Nullable
            // 发送失败时回调
        }
        @Override
        public void notImplemented() {
            // 若是该通道在Flutter端未实现,会回调这里
        }
    });
    复制代码

    第一个参数是 Flutter 端经过 call.method 得到的标示。

    第二个参数是须要发送的数据。

    第三个参数用于监听通讯是完成状态。

  • Native - iOS 端:

    channel.invokeMethod(name, arguments: value) {
      (result: Any?) -> Void in
      if let error = result as? FlutterError {
        os_log("%@ failed: %@", type: .error, name, error.message!)
      } else if FlutterMethodNotImplemented.isEqual(result) {
        os_log("%@ not implemented", type: .error, name)
      } else {
        os_log("%@", type: .info, result as! NSObject)
      }
    }复制代码

目录传送门:《Flutter快速上手指南》先导篇

如何找到我?

传送门:CoorChice 的主页

传送门:CoorChice 的 Github

相关文章
相关标签/搜索