从事Flutter开发过程中,有的时候Flutter的功能明显是不够用的,这个时候就要使用Flutter调用原生或者原生调用Flutter了。
那么我们如何进行Flutter和原生代码之间的互相调用呢?其实Flutter已经为我们提供了对应的方法,我们只需要按照步骤进行实现就行了。
Flutter为我们提供了三种与原生互动的方式
1、
MethodChannel | 用于 Flutter 与 原生平台之间函数的互相调用 |
2、
BasicMessageChannel | 它传递的是字节数组,使用时自定义编解码器 |
3、
EventChannel | 用于 Flutter 与 原生平台之间事件的通信 |
今天我们主要以MethodChannel实现Fluter与原生互相调用
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模拟器,可以看一下实现效果
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与原生代码互相调用