Flutter
是UI
框架,如果我们要 调用系统的蓝牙、实现消息推送等底层 的功能时,单使用Flutter
就显得有点力不从心了,Flutter
为了解决这个问题,提供了方法通道(Method Channel)
机制。
使用方法通道在客户端(Flutter)和宿主(平台)之间传递消息,如下图所示:
图片来源:https://flutter.dev/docs/development/platform-integration/platform-channels
从上图中可以看到,在 Android
中是通过FlutterView
去和底层的API
交互,而在iOS
中则是通过 FlutterViewController
去和底层的API
交互。
可以看一下MethodChannel
的构造函数:
const MethodChannel(
this.name, // 用指定的 name 创建一个 MethodChannel
[this.codec = const StandardMethodCodec(), BinaryMessenger binaryMessenger ]// 可选参数
)
通过构造函数我们知道使用MethodChanle
需要传递一个特定的name
去标识该方法通道。
那么完整的使用MethodChannel
的流程是怎样的呢?
通过上面的图片我们也知道,要使用方法通道需要在host
端和client
端做一些处理。
首先在client
端(Flutter)做如下步骤:
Flutter
端创建MthodChannel
实例.invokeMethod(String method, [ dynamic arguments ])
调用方法然后在host
端(Android、iOS),做如下步骤:
Android
为例。MainActivity
中的onCreate
方法中添加MethodChannel
的回调处理// CHANNEL 的值和 client 中MethodChannel 构造参数中的 name 要一致
MethodChannel(flutterView, CHANNEL).setMethodCallHandler { call, result ->
// 做相关逻辑处理
}
下面通过 3 个示例来看一下MethodChannel
如何使用。
由于对
iOS
不熟悉,以下示例仅在Android
端操作。示例主要是描述了host
和client
之间数据的传递和接收。
client
跳转host
获取电池电量并返回给client
显示。示例来源:实现源码可查看 Flutter 中文网
跳转host(Android)
并将电池电量返回给client(Flutter)
显示:
// Flutter 端获取电池电量(getBatteryLevel 和 Android 中定义的方法一样,返回值是 Int,所以通过 Int 接收。)
final int result = await platform.invokeMethod('getBatteryLevel');
setState(() {
_batteryLevel = result ; // 刷新返回的结果
});
// 而在 Android 端通过判断 getBatteryLevel 方法名是否一致,然后去执行具体的电量获取
val batteryLevel = getBatteryLevel() // 获取电池电量
if (batteryLevel != -1) {
// 返回获取到的电量 success 接收的是个 Object
result.success(batteryLevel)
}else {
result.error("UNAVAILABLE", "Battery level not available.", null)
}
接下来看看client
如何给host
传递数据。
client
跳转host
并传递参数,这里以Android
为例 将传递appId 和 packageName
传递给给host
。模拟器没有应用商店可能会出问题。
主要是在调用invokMethod
时传入参数:
final int result = await platform.invokeMethod('openAppStore',{
'appId': "123456",
'packageName': "com.meizu.mstore",
});
源码中有这么一段话:
/// The logical identity of the channel is given by its name. Identically named
/// channels will interfere with each other's communication.
大致意思是:通道的逻辑标识由其名称给出。名称相同的///通道将干扰彼此的通信。