美文网首页
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