Flutter 学习之路(十一)Flutter与原生互相调用

从事Flutter开发过程中,有的时候Flutter的功能明显是不够用的,这个时候就要使用Flutter调用原生或者原生调用Flutter了。

那么我们如何进行Flutter和原生代码之间的互相调用呢?其实Flutter已经为我们提供了对应的方法,我们只需要按照步骤进行实现就行了。


Flutter为我们提供了三种与原生互动的方式

1、

MethodChannel 用于 Flutter 与 原生平台之间函数的互相调用

2、

BasicMessageChannel 它传递的是字节数组,使用时自定义编解码器

3、

EventChannel 用于 Flutter 与 原生平台之间事件的通信

今天我们主要以MethodChannel实现Fluter与原生互相调用

1、Flutter调用原生

1、Flutter代码

首先就是要创建MethodChannel了,每个 channel 都可以处理多个方法的调用,在 handler 对象中根据方法名做分发即可

那么我们如何创建MethodChannel呢?

var channel = MethodChannel("flutterCallNative");

 创建完channel后,剩下的就是调用方法了

try {
   // 通过渠道,调用原生代码代码的方法,"flutterCallNativeMethod"为要调用的方法名
   Future future =
          channel.invokeMethod("flutterCallNativeMethod", {"msg": "想要传递的信息"});
  // 打印执行的结果
   print(future.toString());
} on PlatformException catch (e) {
   print(e.toString());
}

到此就完成了Flutter的代码,我们为了方便可以都写在一个一个方法里面的。

2、安卓代码(Kotlin)

我们打开Flutter代码中的安卓项目,然后找到MainActivity。

然后使用如下代码

    // Flutter 调用原生
    /* ======================================================= */
    /* Override/Implements Methods                             */
    /* ======================================================= */
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        val messenger = flutterEngine.dartExecutor.binaryMessenger
        // 新建一个 Channel 对象,flutterCallNative为Flutter中生命的Channel名字
        val channel = MethodChannel(messenger, "flutterCallNative")
        // 为 channel 设置回调
        channel.setMethodCallHandler { call, res ->
            // 根据方法名,分发不同的处理
            when (call.method) {
                // Flutter中声明的方法名
                "flutterCallNativeMethod" -> {
                    // 获取传入的参数
                    val msg = call.argument("msg")
                    Log.i("ZHP", "正在执行原生方法,传入的参数是:「$msg」")
                    // 通知执行成功
                    res.success("这是执行的结果")
                }
                else -> {
                    // 如果有未识别的方法名,通知执行失败
                    res.error("error_code", "error_message", null)
                }
            }
        }
    }

3、iOS 代码(Swift)

同样我们在Flutter项目找到iOS文件夹然后右键用Xcode打开或者直接在Flutter中打开文件也可以,找到AppDelegate,然后代码如下

private func flutterCallNative(){
        // 注册渠道
        let controller:FlutterViewController = window.rootViewController as! FlutterViewController
        // flutterCallNative 为Flutter中的声明的渠道名
        let channel = FlutterMethodChannel(name: "flutterCallNative", binaryMessenger: controller.binaryMessenger)
        channel.setMethodCallHandler { (call, res) in
            // 根据函数名做不同的处理
            switch(call.method) {
                // 这里就是Flutter中声名的方法名
                case "flutterCallNativeMetod":
                    // 这里为了减少方法里的内容又创建了一个心得方法,其实完全可以下面方法的完全的放入到此处
                    self.yourMethodName(call: call, result: res)
                default:
                    res(nil)
            }
        }
    }

    /* ======================================================= */
    /*                                        */
    /* ======================================================= */
 private func yourMethodName(call: FlutterMethodCall, result: FlutterResult ) {
        // 获取传入的参数字典
        let params = call.arguments as? NSDictionary
        var msg = ""
        if (params != nil) {
            // 获取具体的参数值
            msg = params!["msg"] as? String ?? ""
        }
        let alertView = UIAlertView.init(title: "提示", message: msg, delegate: self, cancelButtonTitle: "确定")
        alertView.show()
        // 打印日志
        print("正在执行原生方法,传入的参数是:" + msg)
        // 通知结束
        result("调用成功了")
    }

然后在下面的方法调用一下就可以了

override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    flutterCallNative()
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

到此Flutter调用原生就完成了。

我这里使用的是iOS模拟器,可以看一下实现效果

Flutter 学习之路(十一)Flutter与原生互相调用_第1张图片


2、原生调用Flutter

1、Flutter代码

// 原生调用Flutter
  void _initChannel() {
    // nativeCallFlutter 注册渠道
    var channel = MethodChannel("nativeCallFlutter");
    channel.setMethodCallHandler((call) {
      // 同样也是根据方法名分发不同的函数
      switch(call.method) {
        // nativeCallFlutterMethod 方法名
        case "nativeCallFlutterMethod": {
          String msg = call.arguments["msg"];
          print("Native 调用 Flutter 成功,参数是:$msg");
        }
      }
      return null;
    });
  }

2、安卓代码(Kotlin)

    /* 原生调用 Flutter */
    /* ======================================================= */
    /* Override/Implements Methods                             */
    /* ======================================================= */

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)

        val messenger = flutterEngine.dartExecutor.binaryMessenger

        // 新建一个 Channel 对象,nativeCallFlutter为Flutter中声明的渠道
        val channel = MethodChannel(messenger, "nativeCallFlutter")

        // 调用 Flutter 中的方法
        val params = mapOf(
                "msg" to "这是来自 Android 端的参数"
        )
        // 这里nativeCallFlutterMethod为Flutter中的方法名
        channel.invokeMethod("nativeCallFlutterMethod", params)
    }

3、iOS代码(Swift)

// MARK:- 原生调用Flutter
    private func nativeCallFlutter(){
        let controller:FlutterViewController = window.rootViewController as! FlutterViewController
        // 创建渠道nativeCallFlutter为Flutter中声明的名字
        let channel = FlutterMethodChannel(name: "nativeCallFlutter", binaryMessenger: controller.binaryMessenger)
        // 通过渠道调用 Flutter 的方法,nativeCallFlutterMethod为Flutter的方法
        var params: Dictionary = ["msg": "这是来自 iOS 端的参数"]
                channel.invokeMethod("nativeCallFlutterMethod", arguments: params)
    }

代码就完成了Flutter和原生之间的调用了。

如果Flutter以后越来越成熟,我相信Flutter与原生的互相调用频次会越来越少的,但是现在Flutter和原生之间的调用还是不可避免的

参考:Flutter与原生互相调用、Flutter与原生代码互相调用

 

 

你可能感兴趣的:(Flutter,flutter)