经过阅读 混合开发(一) 和 混合开发(二) ,相信你已经让一个 原生 + Flutetr 的混合应用运行起来了。git
恭喜你 🎉🎉🎉!github
如今,你可能遇到了 Flutter代码 和 原生代码 以前没法互相调用的难题。bash
由于 Flutter 做为独立于原生 Android 的一套开发框架,确定是不能直接互相调用和愉快的交换信息的。架构
如今,来看看 Flutter 是如何解决这些问题的。框架
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 |
MethodChannel 经过特定的通道,来创建起 Flutter 和 Native 之间通讯桥梁。
固然,咱们须要在 Flutter 和 Native 两端都须要定义相同的通道。
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 就行。
在一个大型的项目中。你可能会须要创建不少的通讯通道,因此建议统一的管理这些通讯通道。
创建好通讯通道,来看看如何让 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)
}
}
复制代码
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)
}
}复制代码