美文网首页
Flutter-与 Native通信

Flutter-与 Native通信

作者: JerrySi | 来源:发表于2019-08-10 08:26 被阅读0次

Flutter定义了三种不同类型的Channel,它们分别是

  • BasicMessageChannel:用于传递字符串和半结构化的信息,这个用的比较少
  • MethodChannel:用于传递方法调用(method invocation)通常用来调用native中某个方法
  • EventChannel: 用于数据流(event streams)的通信。有监听功能,比如电量变化之后直接推送数据给flutter端。

目前我的项目中只使用了MethodChannel,所以下面主要以MethodChannel部分代码演示。

如果你还想了解其他2种Channel,可以查看下面这篇文章
https://www.jianshu.com/p/39575a90e820

1. Native层

let flutterChannel = FlutterMethodChannel(name: "srs.flutter.io/flutter", binaryMessenger: flutterViewController)

// 注册方法等待flutter页面调用
flutterChannel.setMethodCallHandler { (call, result) in
    NSLog("Srs==> call.method:\(call.method)")
    NSLog("Srs==> arguments:\(String(describing: call.arguments))")
    
    // 返回的err给flutter
    if call.method == "getNativeErrResult" {
        let error: FlutterError = FlutterError(code: "UNAVAILABLE", message: "info unavailable", details: "UNAVAILABLE=>info unavailable")
        result(error)
    } else if call.method == "getNativeScsResult" {
        // 通过result返回给Flutter回调结果
        let name = ["name": "Srs"]
        result(name)
   
    } else if call.method == "dismiss" {
        // 跳出页面
        VCManager.popTopView()
        
    } else if call.method == "next" {
        // 原生调用了Flutter方法
        flutterChannel.invokeMethod("getFlutterResult", arguments: ["name": "Srs"], result: { (result) in
            NSLog("Srs==> Flutter Result:\(result)")
        })
        
    } else {
        result(FlutterMethodNotImplemented)
    }
}

这里使用的iOS代码,Android端代码也类似。首先通过设置MethodCall的监听,然后根据method处理Flutter端需要的操作逻辑。如果是"next"的时候,原生调用Flutter方法。

2. Flutter层

const platform = const MethodChannel('srs.flutter.io/flutter'); // 交互通道

// 等待Native调用
platform.setMethodCallHandler((methodCall) {
  debugPrint("Srs===> flutter===> methodCall.method " + methodCall.method);
  // 获取参数
  var arguments = new Map<String, dynamic>.from(methodCall.arguments);
  debugPrint(
      "Srs===> flutter===> methodCall.arguments " + arguments.toString());

  return Future.value({"key1": "value1", "key2": "value2"});
});

// 调用Native
Future<void> invokeNative() async {
  String backString;
  try {
    var result = await platform.invokeMethod('dismiss', {});
    backString = 'Native return $result';
  } on PlatformException catch (e) {
    backString = "Failed to get native return: '${e.message}'.";
  }
  debugPrint("Srs===> flutter==>flutter:" + backString);
}
invokeNative();

首先通过设置MethodCall的监听,同样可以根据method处理Native端需要的操作逻辑, 我这里直接返回数据了。另外通过invokeMethod来调用Native方法。

通信传递过程

Flutter具体是怎么和Native传递消息的呢,本文在https://www.jianshu.com/p/39575a90e820https://juejin.im/post/5c88be3cf265da2d9809403d基础上进行了整理。

  1. Flutter端使用invokeMethod方法发起方法调用
  2. invokeMethod方法会将其入参message和arguments封装成一个MethodCall对象,并使用MethodCodec将其编码为二进制格式数据
  3. 通过BinaryMessages将消息发出

BinaryMessenger是Native端与Flutter端通信的工具,其通信使用的消息格式为二进制格式数据。


binaryMessager.png

大概格式类似于这样:
BinaryMessenger = [BinaryMessageHandler,BinaryMessageHandler...]
BinaryMessageHandler = {"channel name": Handler}
也就是一个项目可以多个channel,上面示例代码只有一个channel。

  1. 最终调用到ui.window.sendPlatformMessage方法,至此进入C++层

在C++层通过类似Java的JNI技术给Native层发消息,最终会被Native端预先注册的Window_sendPlatformMessage接受到。

  1. sendPlatformMessage首先会把来自Flutter端的三个参数(name、data、callback)创建成一个PlatformMessage对象,就是C++认识的对象,
  2. 接着进入PlatformView的HandlePlatformMessage
    2.1 针对iOS直接进入PlatformMessageRouter根据Channel找到对应的Handle处理,处理完根据PlatformMessage里面Response返回给Flutter。
    2.2 针对Android,因为JAVA无法直接和C++通信,要多一步JNI操作。PlatformView会通过JNI发送到Java层FlutterNativeView的handlePlatformMessage方法,在该方法里面根据Channel找到对应的Handle处理,处理完再通过JNI返回给PlatformView,根据PlatformMessage里面Response返回给Flutter。

至此,一次从Flutter发起的方法调用就完整结束了。

相关文章

网友评论

      本文标题:Flutter-与 Native通信

      本文链接:https://www.haomeiwen.com/subject/zoxfjctx.html