美文网首页
原生Android与Flutter通信方式(一)

原生Android与Flutter通信方式(一)

作者: aimaile | 来源:发表于2019-04-21 18:32 被阅读0次

    通信在任何程序中都是举足轻重的,在做Flutter开发的时候通常离不了Flutter和Native之间的通信,比如:初始化Flutter时Native向Dart传递数据,Dart调用Native的相册选择图片,Dart调用Native的模块进行一些复杂的计算,Native将一些数据(GPS信息,陀螺仪,传感器等)主动传递给Dart等。当然,这种通信的感觉有点像原生app调用C/C++,不用担心这里不需要写jni,不需要会cmake,但是这里需要懂原生app基本开发了,同理ios也是一样的。

    言归正传,这里将向大家介绍在Flutter中Dart和Native之间通信的几种方式以及其原理和使用技巧;接下来我将分场景来介绍Dart 和Native之间的通信。
    几种通信场景:
    1、初始化Flutter时Native向Dart传递数据;
    2、Native发送数据给Dart;
    3、Dart发送数据给Native;
    4、Dart发送数据给Native,然后Native回传数据给Dart;

    Flutter 与 Native通信机制

    在讲解Flutter 与 Native之间是如何传递数据之前,我们先来了解下 Flutter与Native的通信机制,Flutter和Native的通信是通过Channel来完成的。

    消息使用Channel(平台通道)在客户端(UI)和主机(平台)之间传递,如下图所示:


    flutter通信.png

    Flutter中消息的传递是完全异步的;

    Channel所支持的数据类型对照表:

    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

    Flutter定义了三种不同类型的Channel:

    BasicMessageChannel:用于传递字符串和半结构化的信息,持续通信,收到消息后可以回复此次消息,如:Native将遍历到的文件信息陆续传递到Dart,在比如:Flutter将从服务端陆陆续获取到信息交个Native加工,Native处理完返回等;

    MethodChannel:用于传递方法调用(method invocation)一次性通信:如Flutter调用Native拍照;

    EventChannel: 用于数据流(event streams)的通信,持续通信,收到消息后无法回复此次消息,通常用于Native向Dart的通信,如:手机电量变化,网络连接变化,陀螺仪,传感器等;

    这三种类型的类型的Channel都是全双工通信,即A <=> B,Dart可以主动发送消息给platform端,并且platform接收到消息后可以做出回应,同样,platform端可以主动发送消息给Dart端,dart端接收数后返回给platform端。

    BasicMessageChannel用法

    Native端:

    构造方法

    BasicMessageChannel(BinaryMessenger messenger, String name, MessageCodec<T> codec)
    
    • BinaryMessenger messenger - 消息信使,是消息的发送与接收的工具;
    • String name - Channel的名字,也是其唯一标识符;
    • MessageCodec<T> codec - 消息的编解码器,它有几种不同类型的实现:
    • BinaryCodec - 最为简单的一种Codec,因为其返回值类型和入参的类型相同,均为二进制格式(Android中为ByteBuffer,iOS中为NSData)。实际上,BinaryCodec在编解码过程中什么都没做,只是原封不动将二进制数据消息返回而已。或许你会因此觉得BinaryCodec没有意义,但是在某些情况下它非常有用,比如使用BinaryCodec可以使传递内存数据块时在编解码阶段免于内存拷贝;
    • StringCodec - 用于字符串与二进制数据之间的编解码,其编码格式为UTF-8;
    • JSONMessageCodec - 用于基础数据与二进制数据之间的编解码,其支持基础数据类型以及列表、字典。其在iOS端使用了NSJSONSerialization作为序列化的工具,而在Android端则使用了其自定义的JSONUtil与StringCodec作为序列化工具;
    • StandardMessageCodec - 是BasicMessageChannel的默认编解码器,其支持基础数据类型、二进制数据、列表、字典,其工作原理;

    setMessageHandler方法

    void setMessageHandler(BasicMessageChannel.MessageHandler<T> handler)
    
    • BasicMessageChannel.MessageHandler<T> handler - 消息处理器,配合BinaryMessenger完成消息的处理;
      在创建好BasicMessageChannel后,如果要让其接收Dart发来的消息,则需要调用它的setMessageHandler方法为其设置一个消息处理器。

    BasicMessageChannel.MessageHandler原型

    public interface MessageHandler<T> {
        void onMessage(T var1, BasicMessageChannel.Reply<T> var2);
    }
    
    • onMessage(T var1, BasicMessageChannel.Reply<T> var2) - 用于接受消息,var1是消息内容,var2是回复此消息的回调函数;

    send方法原型

    void send(T message)
    void send(T message, BasicMessageChannel.Reply<T> callback)
    
    
    • T message - 要传递给Dart的具体信息;
    • BasicMessageChannel.Reply<T> callback - 消息发出去后,收到Dart的回复的回调函数;

    在创建好BasicMessageChannel后,如果要向Dart发送消息,可以调用它的send方法向Dart传递数据。

    public class BasicMessageChannelPlugin implements BasicMessageChannel.MessageHandler<String>, BasicMessageChannel.Reply<String> {
        private final Activity activity;
        private final BasicMessageChannel<String> messageChannel;
    
        static BasicMessageChannelPlugin registerWith(FlutterView flutterView) {
            return new BasicMessageChannelPlugin(flutterView);
        }
    
        private BasicMessageChannelPlugin(FlutterView flutterView) {
            this.activity = (Activity) flutterView.getContext();
            this.messageChannel = new BasicMessageChannel<>(flutterView, "BasicMessageChannelPlugin", StringCodec.INSTANCE);
            //设置消息处理器,处理来自Dart的消息
            messageChannel.setMessageHandler(this);
        }
    
        @Override
        public void onMessage(String s, BasicMessageChannel.Reply<String> reply) {//处理Dart发来的消息
            reply.reply("BasicMessageChannel收到:" + s);//可以通过reply进行回复
            if (activity instanceof IShowMessage) {
                ((IShowMessage) activity).onShowMessage(s);
            }
            Toast.makeText(activity, s, Toast.LENGTH_SHORT).show();
        }
    
        /**
         * 向Dart发送消息,并接受Dart的反馈
         *
         * @param message  要给Dart发送的消息内容
         * @param callback 来自Dart的反馈
         */
        void send(String message, BasicMessageChannel.Reply<String> callback) {
            messageChannel.send(message, callback);
        }
    
        @Override
        public void reply(String s) {
    
        }
    }
    
    

    Dart端:

    构造方法原型

    const BasicMessageChannel(this.name, this.codec);
    
    • String name - Channel的名字,要和Native端保持一致;
    • MessageCodec<T> codec - 消息的编解码器,要和Native端保持一致,有四种类型的实现具体可以参考Native端的介绍;

    setMessageHandler方法原型

    void setMessageHandler(Future<T> handler(T message))
    
    • Future<T> handler(T message) - 消息处理器,配合BinaryMessenger完成消息的处理;

    在创建好BasicMessageChannel后,如果要让其接收Native发来的消息,则需要调用它的setMessageHandler方法为其设置一个消息处理器。

    send方法原型

     Future<T> send(T message)
    
    • T message - 要传递给Native的具体信息;
    • Future<T> - 消息发出去后,收到Native回复的回调函数;

    在创建好BasicMessageChannel后,如果要向Native发送消息,可以调用它的send方法向Native传递数据。

    import 'package:flutter/services.dart';
    
    static const BasicMessageChannel _basicMessageChannel =
          const BasicMessageChannel('BasicMessageChannelPlugin', StringCodec());
    
    //使用BasicMessageChannel接受来自Native的消息,并向Native回复
    _basicMessageChannel
        .setMessageHandler((String message) => Future<String>(() {
              setState(() {
                showMessage = message;
              });
              return "收到Native的消息:" + message;
            }));
    //使用BasicMessageChannel向Native发送消息,并接受Native的回复
    String response;
        try {
           response = await _basicMessageChannel.send(value);
        } on PlatformException catch (e) {
          print(e);
        }
    

    相关文章

      网友评论

          本文标题:原生Android与Flutter通信方式(一)

          本文链接:https://www.haomeiwen.com/subject/cyndgqtx.html