iOS端与Flutter通信

Flutter与Native之间通过Channel进行通信。消息使用Channel在客户端和主机之间传递,且Flutter中消息的传递是异步的,如下如所示:


Channel.png

Flutter中定义了三种类型的Channel

  • BasicMessageChannel
    用于传递字符串和半结构化的消息,收到消息后可以回复消息,持续进行通信。
  • MethodChannel
    用于方法调用,是一次性通信。如Flutter调用原生相机相册等;
  • EventCHannel
    用于数据流的通信,也是持续性通信,但收到消息后不能回复消息。通常用户原生想Flutter传递手机电量变化、网络连接变化等;
BasicMessageChannel

BasicMessageChannel的创建

/**
 * @param name channel的名字.
 * @param messenger 消息信使.
 * @param codec 消息编解码器.
 */
+ (instancetype)messageChannelWithName:(NSString*)name
                       binaryMessenger:(NSObject*)messenger
                                 codec:(NSObject*)codec;

消息编辑码器有如下几种不同类型:

  • BinaryCodec
    返回值类型和入参类型均为二进制格式。实际上BinaryCodec在编解码过程中只是将二进制数据消息原封不动的返回。BinaryCodec在某些情况下非常有用,使用BinaryCodec可以使传递内存数据块时在编解码阶段免于内存拷贝;

  • FLutterStringCodec
    用于字符串和二进制之间的编解码,编码格式为UTF-8;

  • FlutterJSONMessageCodec
    用于基础数据和二进制数据之间的编解码,支持基础数据类型、数组、字典。iOS端使用NSJSONSerialization作为序列化工具。

  • FLutterBinaryCodec
    是FlutterBinaryMessenger的默认编解码器,支持基础数据类型、二进制数据、数组、字典。

Native端设置消息处理器接收Dart消息

// channelName 要与Dart端保持一致
static NSString *const kMessageChannelName = @"BasicMessageChannel";

- (void)initChannel {
    self.messageChannel = [FlutterBasicMessageChannel messageChannelWithName:kMessageChannelName binaryMessenger:self.flutterController codec:[FlutterStringCodec sharedInstance]];
    __weak typeof(self) weakSelf = self;
  // 处理dart发送的消息
    [self.messageChannel setMessageHandler:^(id  _Nullable message, FlutterReply  _Nonnull callback) {
        callback([NSString stringWithFormat:@"BasicMessageChannel收到:%@",message]);
        [weakSelf showMessage:message];
    }];
}   

Dart端发送消息给Native

//声明BasicMessageChannel
  static const BasicMessageChannel _basicMessageChannel= const BasicMessageChannel('messageChannelName',StringCodec());

  void _sendToNative(value) async {
    String response;
    try{
      response = await _basicMessageChannel.send('received from BasicMessageChannel');
    }on PlatformException catch (e){
      print(e);
    }
  }

Native端发送消息给Dart端并接收Dart端回复

- (IBAction)editingChanged:(id)sender {
    [self.messageChannel sendMessage:self.textField.text reply:^(id  _Nullable reply) {
        if (reply) {
            [self showMessage:reply];
        }
    }];
}

Dart端设置消息处理器接收Native消息并返回回复内容

@override
  void initState() {
    _basicMessageChannel.setMessageHandler((String message) => Future((){
      setState(() {
        showMessage = 'BasicMessageChannel:'+message;
      });
      return "received message from Native:" + message;
    }));

    super.initState();
  }
MethodChannel

Dart端使用MethodChannel向Native发送消息,并接受Native的回复

//创建 “ MethodChannel”这个名字要与原生创建时的传入值保持一致
 static const MethodChannel _methodChannelPlugin = const MethodChannel('MethodChannel');

/*
 * invokeMethod(String method, [dynamic arguments])
 * method:要调用的方法名
 * arguments:传参
 */
response = await _methodChannelPlugin.invokeMethod('send', value);

Native端设置消息处理器接收Dart消息

static NSString *const kEventChannelName = @"EventChannel";
static NSString *const kMethodChannelName = @"MethodChannel";
- (void)initMethodChannel {
    self.methodChannel = [FlutterMethodChannel methodChannelWithName:kMethodChannelName binaryMessenger:self.flutterController];
    __weak typeof(HybridViewController) *weakSelf = self;
    [self.methodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult  _Nonnull result) {
        if ([call.method isEqualToString:@"send"]) {//调用哪个方法
            result([NSString stringWithFormat:@"MethodChannel:收到Dart消息:%@",call.arguments]);
            [weakSelf showMessage:[NSString stringWithFormat:@"收到Dart消息:%@ by MethodChannel",call.arguments]];
        }
    }];
}
EventChannel

Native端构造方法

/**
 * @param name  channel name唯一标识符与Dart端一致.
 * @param messenger 消息信使.
 */
self.eventChannel = [FlutterEventChannel eventChannelWithName:kEventChannelName binaryMessenger:self.flutterController];
//设置消息处理器的代理
[self.eventChannel setStreamHandler:self];

通过下面代理方法处理消息

// FlutterEventSink:传输数据的载体
@property (nonatomic) FlutterEventSink eventSink;

#pragma mark - 
//这个onListen是Flutter端开始监听这个channel时的回调,第二个参数 EventSink是用来传数据的载体
- (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments eventSink:(FlutterEventSink)eventSink {
    // arguments flutter给native的参数
    // 回调给flutter, 建议使用实例指向,因为该block可以使用多次
    self.eventSink = eventSink;
    return nil;
}

/// flutter不再接收
- (FlutterError* _Nullable)onCancelWithArguments:(id _Nullable)arguments {
    // arguments flutter给native的参数
    self.eventSink = nil;
    return nil;
}

Native发送消息给Dart端

- (void)sendMessageByEventChannel:(NSString *)message{
    if (self.eventSink) {
        self.eventSink(message);
    }
}

Dart端接收Native传来的数据

// 创建 EventChannel
static const EventChannel _eventChannelPlugin = EventChannel('EventChannel');
// 初始化一个广播流从channel中接收数据,返回的Stream调用listen方法完成注册,需要在页面销毁时调用Stream的cancel方法取消监听
StreamSubscription _streamSubscription;

@override
  void initState() {
    _streamSubscription = _eventChannelPlugin
        .receiveBroadcastStream()
        .listen(_onToDart, onError: _onToDartError);
    super.initState();
  }

 @override
  void dispose() {
    if (_streamSubscription != null) {
      _streamSubscription.cancel();
      _streamSubscription = null;
    }
    super.dispose();
  }

void _onToDart(message) {
    setState(() {
      showMessage = 'EventChannel:'+message;
    });
  }

  void _onToDartError(error) {
    print(error);
  }

你可能感兴趣的:(iOS端与Flutter通信)