美文网首页
Flutter与原生如何进行通信

Flutter与原生如何进行通信

作者: 天上飘的是浮云 | 来源:发表于2021-06-10 15:41 被阅读0次

      用Flutter这样的跨平台技术进行商业级项目开发时,几乎不可避免的需要和Native进行通信,比如不同平台的底层服务如电量变化、网络连接变化、陀螺仪、传感器等等都有各自不同的实现,以及编译期的一些配置,比如包名、版本号、第三方依赖APPKEY等都需要通过原生的方法去获取。所以得学一哈Native和Flutter的通信方式是非常有必要的

    前话

    Native和Flutter之间可以通过Platform Channels APIs进行通信,
    Flutter定义了三种不同类型的Channel:


    • MethodChannel:用于传递方法调用(method invocation),适用于一次性通信

    • BasicMessageChannel:用于传递字符串和半结构化的消息,持续通信可回复

    • EventChannel: 用于事件流的发送(event streams),持续通信不可回复

    一、MethodChannel通信

    MethodChannel是最常用的Native和Flutter的通信方式,主要用于Flutter调用Native端方法,如调用Native相机功能

    为了便于理解,这里我介绍一个前两天在公司项目中实际用到MethodChannel的场景。基本现在Android APP都会涉及到多渠道打包问题,针对不同的渠道,我们可能会在编译脚本(build文件)中进行一些不同的配置。但是Flutter如何才能拿到Android Gradle中的配置信息呢?其实很简单,也就是我们可以先通过Android代码拿到BuildConfig中的数据,再通过Flutter与Android进行通信拿到数据。这种一次性的调用Android中代码的情况就需要用到MethodChannel

    1.1 Android端

    创建MethodChannel,通过setMethodCallHandler接收Flutter端的方法调用

        private val Method_Channel = "com.example.flutter_test_call/methodChannel"
        override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
            super.configureFlutterEngine(flutterEngine)
            //1.创建android端的MethodChannel
            val methodChannel = MethodChannel(flutterEngine.dartExecutor, Method_Channel)
            //2.通过setMethodCallHandler响应Flutter端的方法调用
            methodChannel.setMethodCallHandler { call, result ->
                //判断调用的方法名
                if(call.method.equals("testMethodCall")){
                    //获取传递的参数
                    Log.e("test", "Have received Test Method Call :${call.arguments}")
                    //返回结果给Flutter端
                    result.success(BuildConfig.DEBUG.toString() + " " +"yes")
                }
            }
        }
    
    1.2 Flutter端

    Flutter端同样也有MethodChannel,可以通过类似方法调用的方式,调用Native层的方法,并拿到返回值

      String Method_Channel = "com.example.flutter_test_call/methodChannel";
      Future<void> testMethodCall() async {
        //1.创建Flutter端的MethodChannel
        MethodChannel _methodChannel = MethodChannel(Method_Channel);
        //2.通过invokeMethod调用Native方法,拿到返回值
        String debugString = await _methodChannel.invokeMethod("testMethodCall", "give me debug info");
        print('test debugString=$debugString');
      }
    

    这里要注意两点:

    • ChannelName要与Native端保持一致(即com.example.flutter_test_call/methodChannel)
    • MethodName要与Native端保持一致(即testMethodCall)

    二、BasicMessageChannel通信

    BasicMessageChannel用于Native和Flutter互相发送消息,一方给另一方发送消息,收到消息之后给出回复

    2.1 Android给Flutter发送消息
    2.1.1 Android端

    创建一个BasicMessageChannel,通过send方法发送消息

    private val Basic_Method_Channel = "com.example.flutter_test_call/basicMethodChannel"
    
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        //1.创建android端的BasicMessageChannel
        val basicMethodChannel = BasicMessageChannel(flutterEngine.dartExecutor, Basic_Method_Channel, StringCodec.INSTANCE)
        //2.向Flutter端发送消息
        basicMethodChannel.send("Hello, this is BasicMethodChannel Send msg!") {         
                replyString ->            
                   Log.i("test", "收到了Flutter端发来的回复:$replyString")
        }
    }
    

    发送的消息会以二进制的形式进行处理,所以要针对不同类型的数据进行二进制编码

    编码类型 消息格式
    BinaryCodec 发送二进制消息
    JSONMessageCodec 发送Json格式消息
    StandardMessageCodec 发送基本型数据
    StringCodec 发送String类型消息
    2.1.2 Flutter端

    Flutter端同样也有BasicMessageChannel,通过setMessageHandler接收并回复消息

    String Basic_Method_Channel = "com.example.flutter_test_call/basicMethodChannel";
    initBasicMethodCall(){
      //1.创建Flutter端的BasicMessageChannel
      basicMessageChannel = BasicMessageChannel(Basic_Method_Channel, StringCodec());
      //2.接收来自Native的消息,并向Native回复
      basicMessageChannel.setMessageHandler((message) {
        print('test Android端发来的消息:$message');
        return Future.value('黄河黄河,我是长江');
      });
    }
    
    2.2 Flutter给Android发送消息
    2.2.1 Flutter端

    在Flutter端我们也可以通过send方法向Native发送消息,方法的返回值就是Native端的消息回复

    注意flutter和Native的通信都是异步的

    testBasicMethodCall() async {
      String replyString =  await basicMessageChannel?.send("Android, 我是Flutter端!");
      print('test Android端回复的的消息:$replyString');
    }
    
    2.2.2 Android端

    android端通过setMessageHandler设置消息处理器,处理来自Dart的消息,收到消息后通过reply进行回复

        basicMethodChannel.setMessageHandler { message, reply ->
            Log.v("test", "收到了Flutter端发来的消息:$message")
            //通过reply进行回复
            reply.reply("长江长江,我是黄河~")
        }
    

    三、EventChannel通信

    EventChannel用于从Native向Flutter发送通知事件,例如Flutter通过其监听Android的重力感应变化等。与MethodChannel不同,EventChannel是Native到Flutter的单向调用,调用是一对多的,类似Android的BrodcastReceiver

    3.1 Android端

    创建一个EventChannel,在StreamHandler#onLister回调中获取EventSink引用并保存,当重力感应发送变化时,通过eventSink.success向Flutter端发送消息

    private val Event_Channel = "com.example.flutter_test_call/eventChannel"
    var eventSink: EventChannel.EventSink? = null
    fun registerEventChannel(binaryMessenger: BinaryMessenger){
         //1.创建Android端的EventChannel
        val eventChannel = EventChannel(binaryMessenger, Event_Channel)
        //2.在StreamHandler#onLister回调中获取EventSink引用并保存
        eventChannel.setStreamHandler(object : EventChannel.StreamHandler{
            override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
                eventSink = events
            }
    
            override fun onCancel(arguments: Any?) {
                eventSink = null
            }
    
        })
    }
    
    fun getNetWorkType(context : Context){
        var connectivityManager : ConnectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    
        var info = connectivityManager.activeNetworkInfo
        if(info != null){
            if(info?.type == ConnectivityManager.TYPE_WIFI){
                //3.调用eventSink.success向Flutter端发送消息
                eventSink?.success("WIFI")
            }else if(info.type == ConnectivityManager.TYPE_MOBILE){
                eventSink?.success("Mobile")
            }else{
                eventSink?.success("Unkonw")
            }
        }else{
            //3.报错后调用eventSink.error向Flutter端发送消息
            eventSink?.error("error network", "error network", "error network")
        }
    
    }
    
    3.2 Flutter端

    Flutter端接收消息如下所示,要注意使用EventChannel时需要在页面销毁时取消监听,防止内存泄漏

    String eventChannel = 'com.example.flutter_test_call/eventChannel';
    StreamSubscription streamSubscription;
    testEventChannel(){
      //1.创建Flutter端EventChannel
      EventChannel _eventChannel = EventChannel(eventChannel);
      //2.EventChannel#receiveBroadcastStream注册listener,建立监听
      streamSubscription = _eventChannel.receiveBroadcastStream()
        .listen((event) {
          print("Network Status : $event");
      }, onError: (errorcode){
         print('errorcode: $errorcode');
      });
    }
    
    @override
    void dispose() {
      // TODO: implement dispose
      super.dispose();
      //3.页面销毁时需要取消监听,防止内存泄漏
      streamSubscription?.cancel();
    }
    

    申明:禁用于商业用途,如若转载,请附带原文链接。https://www.jianshu.com/p/e376574e2402蟹蟹~

    PS: 写文不易,觉得没有浪费你时间,请给个关注和点赞~ 😁

    相关文章

      网友评论

          本文标题:Flutter与原生如何进行通信

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