美文网首页
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