Flutter iOS之间通信
1.Flutter架构
Flutter框架包括:Framework和Engine,他们运行在各自的Platform上。
Framework是Dart语言开发的,包括Material Design风格的Widgets和Cupertino(iOS-style)风格的Widgets,以及文本、图片、按钮等基础Widgets;还包括渲染、动画、绘制、手势等基础能力。
Engine是C++实现的,包括Skia(二维图形库);Dart VM(Dart Runtime);Text(文本渲染)等。
实际上,Flutter的上层能力都是Engine提供的。Flutter正是通过Engine将各个Platform的差异化抹平。而我们今天要讲的Flutter 与 Native之间的通信,正是通过Engine提供的Platform Channel实现的。
2. Platform Channel
2.1 Flutter App调用Native APIs:
通过上图,我们看到Flutter App是通过Platform Channel调用的Native APIs。
2.2Platform Channel 架构图:
Platform Channel:
- Flutter App (Client),通过MethodChannel类向Platform发送调用消息;
- iOS Platform (Host),通过FlutterMethodChannel类接收调用消息。
PS:消息编解码器,是JSON格式的二进制序列化,所以调用方法的参数类型必须是可JSON序列化的
PS:方法调用,也可以反向发送调用消息。
3.Flutter部分
3.1MethodChannel:Flutter App调用Native APIs
/**
* (1)MethodChannel:Flutter App调用Native APIs
*/
static const MethodChannel _methodChannel = const MethodChannel('samples.flutter.io/battery');
//
Future<String> getBatteryLevel() async {
String batteryLevel;
try {
final int result = await _methodChannel.invokeMethod('getBatteryLevel',{'paramName':'paramVale'});
batteryLevel = 'Battery level: $result%.';
} catch(e) {
batteryLevel = 'Failed to get battery level.';
}
return batteryLevel;
}
首先,我们实例_methodChannel(Channel名称必须唯一),然后调用invokeMethod()方法。invokeMethod()有2个参数:
(1)方法名,不能为空;
(2)调用方法的参数,该参数必须可JSON序列化,可以为空。
3.2EventChannel:Native调用Flutter App
/**
* (2)EventChannel:Native调用Flutter App
*/
static const EventChannel _eventChannel = const EventChannel('samples.flutter.io/charging');
void listenNativeEvent() {
_eventChannel.receiveBroadcastStream().listen(_onEvent, onError:_onError);
}
void _onEvent(dynamic event) {
print("Battery status: ${event == 'charging' ? '' : 'dis'}charging.");
}
void _onError(Object error) {
print('Battery status: unknown.');
}
4.iOS端实现
/**
* Channel名称:必须与Flutter App的Channel名称一致
*/
#define METHOD_CHANNEL "samples.flutter.io/battery";
#define EVENT_CHANNEL "samples.flutter.io/charging";
@implementation AppDelegate
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
/**
* FlutterViewController
*/
FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;
/**
* FlutterMethodChannel & Handler
*/
FlutterMethodChannel* batteryChannel = [FlutterMethodChannel methodChannelWithName:METHOD_CHANNEL binaryMessenger:controller];
[batteryChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
if ([@"getBatteryLevel" isEqualToString:call.method]) {
int batteryLevel = [self getBatteryLevel];
result(@(batteryLevel));
} else {
result(FlutterMethodNotImplemented);
}
}];
/**
* FlutterEventChannel & Handler
*/
FlutterEventChannel* chargingChannel = [FlutterEventChannel eventChannelWithName:EVENT_CHANNEL binaryMessenger:controller];
[chargingChannel setStreamHandler:self];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
(1)Channel名称:必须与Flutter App的Channel名称一致;
(2)FlutterMethodChannel和FlutterEventChannel初始化的时候都需要传递binaryMessenger,即FlutterViewController;
(3)设置FlutterMethodChannel的Handler;
(4)设置FlutterEventChannel的Handler;
3.4.2 FlutterStreamHandler:
@interface AppDelegate () <FlutterStreamHandler>
@property (nonatomic, copy) FlutterEventSink eventSink;
@end
- (FlutterError*)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)eventSink {
self.eventSink = eventSink;
// 监听电池状态
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onBatteryStateDidChange:)
name:UIDeviceBatteryStateDidChangeNotification
object:nil];
return nil;
}
- (FlutterError*)onCancelWithArguments:(id)arguments {
[[NSNotificationCenter defaultCenter] removeObserver:self];
self.eventSink = nil;
return nil;
}
- (void)onBatteryStateDidChange:(NSNotification*)notification {
if (self.eventSink == nil) return;
UIDeviceBatteryState state = [[UIDevice currentDevice] batteryState];
switch (state) {
case UIDeviceBatteryStateFull:
case UIDeviceBatteryStateCharging:
self.eventSink(@"charging");
break;
case UIDeviceBatteryStateUnplugged:
self.eventSink(@"discharging");
break;
default:
self.eventSink([FlutterError errorWithCode:@"UNAVAILABLE"
message:@"Charging status unavailable"
details:nil]);
break;
}
}
如果对你有些许帮助请点个赞,感谢!