Flutter 与原生交互(Android,iOS)

本质上 Flutter 和 原生通信是通过 Channel 来完成的:Flutter中消息的传递是完全异步的;
消息使用 Channel(平台通道) 在客户端(UI) 和主机(p平台)
Flutter 与 native端交互三种方式
1.BasicMessageChannel (用于传递字符串和半结构化信息,持续通信使用,例如dart端将服务器的数据陆续传入到native端)
2.EventMessageChannel(用于数据流event streams的通信,一次性通信)
3.MethodChannel(用于传递方法调用 和native交互大多都是方法调用,所以用这个方式是最常见也最方便的方式且该方式也可以传递字符串和数据流)。
这三种channel 都是可以双向通信的; 即 Dart<==>Native, dart 可以主动发送消息给 native 端, 并且native 接收到 消息可以做出回应;同样 native端也可以主动发送消息给 Dart 端;dart端接收到数据后 返回给 native ;
BasicMessageChannel 示例
dart端:

//flutter端注册BasicMessageChannel 第一个参数name是Channel的名字,也是其唯一标识符 。
							//第二个参数MessageCodec的类型文章最底部详解①
static const basicMessageChannel = BasicMessageChannel("testBasicMessageChannel",StringCodec());
//通过BasicMessageChannel对象注册handler接收回调,并返回自己的信息
basicMessageChannel.setMessageHandler((message) async {
    setState((){
      mMessage = message;
    });
    return "ACK form Dart";
});
//通过BasicMessageChannel对象调用内部的BinaryMessenger发送send消息
  String? message = await basicMessageChannel.send("hello, I'm from Dart");
  print("flutter receive message === $message");

原生端:

//初始化注册 BasicMessageChannel 传入名称名称是和Dart端规定好的应该是唯一的。
var channel = BasicMessageChannel(flutterEngine.dartExecutor.binaryMessenger,
    "testBasicMessageChannel",
    StringCodec.INSTANCE)
//通过BasicMessageChannel的实例注册接收dart端传输的数据,
//参数一message是传过来的数据。
//参数二reply可以通过此对象告知对方结果
channel.setMessageHandler{message,reply->
    Log.d("flutter", "in android Received message = $message")
    reply.reply("ACK from Android")

    //延迟一秒通过BasicMessageChannel实例发送给Dart端数据
    Handler(Looper.getMainLooper()).postDelayed(
        {channel.send("hello Dart,I'm from Android")},1000
    )

EventChannel示例
dart端代码示例:

//flutter端注册EventChannel  参数name是Channel的名字,也是其唯一标识符 。
static const eventChannel = EventChannel("testEventChannel");
//通过EventChannel对象注册一个流回调监听 类似于Android的广播
eventChannel.receiveBroadcastStream().listen((event) {
    print("receive event$event");
    setState(() {
      mMessage = event;
    });
},onError: (error){
  //错误处理
  print("receive error$error");

},
   //错误时是否取消监听
    cancelOnError: true);

原生端代码示例:

//可以将eventchannel的对象返回的eventsink对象设置为全局变量,等方法结束后,可以使用此对象调用success方法告知dart端此方法结束
var eventSink : EventChannel.EventSink? = null;
//初始化注册 EventChannel  传入名称名称是和Dart端规定好的也是其唯一标识符 。
val channel = EventChannel(flutterEngine.dartExecutor.binaryMessenger,
//通过EventChannel的实例对象设置一个事件流。并在一秒后返回给dart端消息
channel.setStreamHandler(object :EventChannel.StreamHandler{
  override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
    eventSink = events;
    Log.d("flutter","EventChannel onListen")
    Handler(Looper.getMainLooper()).postDelayed({
    	Log.d("flutter","I'm Android")
        eventSink?.success("ACK form Android")
            },1000)
    }
  override fun onCancel(arguments: Any?) {
 		Log.d("flutter","onCancel")
    }
})

MethodChannel示例数
MethodChannel通信是在Flutter engine 和framework两层之间进行的通信,所以说在使用MethodChannel是时机是要在FlutterEngine之后
dart端代码示例:

//flutter端注册MethodChannel 
// 第一个参数name是Channel的名字,也是其唯一标识符  EventChannel也是由MethodChannel实现
//codes StandardMethodCodec
static const _channel = MethodChannel("testMethodChannel");

  Future<void> getInfo() async{
    final Map<String,dynamic> map = {
      "name":"flutter",
      "version":"3.3.8",
      "date":"2023-02-20 19:16:01",
    };
    //通过MethodChannel对象直接调用 参数为双方约定好的方法调用名称(非必填)
    String result = await _channel.invokeMethod("getVersion",map);
    print("Method invoke result=$result");
  }

Android端代码示例:

 companion object{
      	//与dart端规定好的方法名称
        const val GET_VERSION = "getVersion"
    }
//初始化注册 MethodChannel   第一个参数name是Channel的名字,也是其唯一标识符(根据不同的name创建不同的channel对象,可以用来区分不同作用的类)
val channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger,
    "testMethodChannel")
//注册MethodChannel处理器
/参数1methodCall 用于接受消息,call是消息内容,它有两个成员变量String类型的call.method表示调用的方法名,Object 类型的call.arguments表示调用方法所传递的入参;
//参数2是回复此消息的回调函数提供了result.success,result.error
channel.setMethodCallHandler{
    methodCall:MethodCall,result:MethodChannel.Result->
    if(methodCall.method == GET_VERSION){
       var name  =methodCall.argument<String>("name")?: ""
       var version  =methodCall.argument<String>("version")?: ""
       var date  =methodCall.argument<String>("date")?: ""
        Log.d("flutter==","name=$name version=$version date=$date")
        result.success("ACK Android")
    }
}

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

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值