【Flutter 混合开发】与原生通信-BasicMessageChannel

Flutter 混合开发系列 包含如下:
- 嵌入原生View-Android
 - 嵌入原生View-iOS
 - 与原生通信-MethodChannel
 - 与原生通信-BasicMessageChannel
 - 与原生通信-EventChannel
 - 添加 Flutter 到 Android Activity
 - 添加 Flutter 到 Android Fragment
 - 添加 Flutter 到 iOS
 每个工作日分享一篇,欢迎关注、点赞及转发。
平台通信的3中方式
Flutter 与 Native 端通信有如下3个方法:
- MethodChannel:Flutter 与 Native 端相互调用,调用后可以返回结果,可以 Native 端主动调用,也可以Flutter主动调用,属于双向通信。此方式为最常用的方式, Native 端调用需要在主线程中执行。
 - BasicMessageChannel:用于使用指定的编解码器对消息进行编码和解码,属于双向通信,可以 Native 端主动调用,也可以Flutter主动调用。
 - EventChannel:用于数据流(event streams)的通信, Native 端主动发送数据给 Flutter,通常用于状态的监听,比如网络变化、传感器数据等。
 
Flutter 端
Flutter 端创建 MethodChannel 通道,用于与原生端通信:
var channel = BasicMessageChannel('com.flutter.guide.BasicMessageChannel',StandardMessageCodec());
com.flutter.guide.BasicMessageChannel 是 BasicMessageChannel 的名称,原生端要与之对应。
发送消息:
var result = await channel.send({'name': 'laomeng', 'age': 18});
- 参数类型任意,多个参数通常使用Map。
 - 返回 Future,原生端返回的数据。
 
完整代码:
class BasicMessageChannelDemo extends StatefulWidget {
  @override
  _BasicMessageChannelDemoState createState() => _BasicMessageChannelDemoState();
}
class _BasicMessageChannelDemoState extends State<BasicMessageChannelDemo> {
  var channel = BasicMessageChannel('com.flutter.guide.BasicMessageChannel',StandardMessageCodec());
  var _data;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: [
          SizedBox(
            height: 50,
          ),
          RaisedButton(
            child: Text('发送数据到原生'),
            onPressed: () async {
              var result = await channel.send({'name': 'laomeng', 'age': 18});
              var name = result['name'];
              var age = result['age'];
              setState(() {
                _data = '$name,$age';
              });
            },
          ),
          Text('原生返回数据:$_data'),
        ],
      ),
    );
  }
}
Android 端
android 下创建 BasicMessageChannelDemo:
class BasicMessageChannelDemo(messenger: BinaryMessenger) : BasicMessageChannel.MessageHandler<Any> {
    private var channel: BasicMessageChannel<Any>
    init {
        channel = BasicMessageChannel(messenger, "com.flutter.guide.BasicMessageChannel", StandardMessageCodec())
        channel.setMessageHandler(this)
    }
    override fun onMessage(message: Any?, reply: BasicMessageChannel.Reply<Any>) {
        val name = (message as Map<String, Any>)["name"]
        val age = (message as Map<String, Any>)["age"]
        var map = mapOf("name" to "hello,$name",
                "age" to "$age"
        )
        reply.reply(map)
    }
}

onMessage 方法在 Flutter 端调用 send 方法后调用,解析方法如下:
override fun onMessage(message: Any?, reply: BasicMessageChannel.Reply<Any>) {
        val name = (message as Map<String, Any>)["name"]
        val age = (message as Map<String, Any>)["age"]
        var map = mapOf("name" to "hello,$name",
                "age" to "$age"
        )
        reply.reply(map)
    }
- message 是传入的参数,由于 Flutter 端传入的是 Map,所以上面的解析按照 Map 解析。
 - reply.reply() 是返回给 Flutter 的结果。
 
Flutter 端解析:
var result = await channel.send({'name': 'laomeng', 'age': 18});
var name = result['name'];
var age = result['age'];
两端的解析要相互对应。
在 MainActivity 启动:
class MainActivity : FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        BasicMessageChannelDemo(flutterEngine.dartExecutor.binaryMessenger)
        flutterEngine.plugins.add(MyPlugin())
    }
}

iOS 端
ios 下创建 MethodChannelDemo,按如下方式:
import Flutter
import UIKit
public class BasicMessageChannelDemo {
    var channel:FlutterBasicMessageChannel
    init(messenger: FlutterBinaryMessenger) {
        channel = FlutterBasicMessageChannel(name: "com.flutter.guide.BasicMessageChannel", binaryMessenger: messenger)
        channel.setMessageHandler { (message, reply) in
            if let dict = message as? Dictionary<String, Any> {
                let name:String = dict["name"] as? String ?? ""
                let age:Int = dict["age"] as? Int ?? -1
                reply(["name":"hello,\(name)","age":age])
            }
        }
    }
}

在 AppDelegate 启动:
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
    MethodChannelDemo(messenger: controller.binaryMessenger)
    BasicMessageChannelDemo(messenger: controller.binaryMessenger)
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

原生端主动发送消息给Flutter
Flutter 端接收数据
@override
  void initState() {
    super.initState();
    channel.setMessageHandler((message) {
      setState(() {
        _nativeData = message['count'];
      });
    });
  }
Android 发送数据
原生端启动定时器,每隔一秒向 Flutter 发送数据,Android 端代码:
class BasicMessageChannelDemo(var activity: Activity, messenger: BinaryMessenger) : BasicMessageChannel.MessageHandler<Any> {
    private var channel: BasicMessageChannel<Any>
    private var count = 0
    init {
        channel = BasicMessageChannel(messenger, "com.flutter.guide.BasicMessageChannel", StandardMessageCodec())
        channel.setMessageHandler(this)
        startTimer()
    }
    fun startTimer() {
        var timer = Timer().schedule(timerTask {
            activity.runOnUiThread {
                var map = mapOf("count" to count++)
                channel.send(map,object :BasicMessageChannel.Reply<Any>{
                    override fun reply(reply: Any?) {
                    }
                })
            }
        }, 0, 1000)
    }
    override fun onMessage(message: Any?, reply: BasicMessageChannel.Reply<Any>) {
        val name = (message as Map<String, Any>)["name"]
        val age = (message as Map<String, Any>)["age"]
        var map = mapOf("name" to "hello,$name",
                "age" to "$age"
        )
        reply.reply(map)
    }
}
注意:Android 端发送数据要在主现场中调用,即:
activity.runOnUiThread {
var map = mapOf("count" to count++)
channel.invokeMethod("timer", map)
}
启动修改如下:
class MainActivity : FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        BasicMessageChannelDemo(this,flutterEngine.dartExecutor.binaryMessenger)
        flutterEngine.plugins.add(MyPlugin())
    }
}

iOS 发送数据
iOS 端启动定时器代码如下:
import Flutter
import UIKit
public class BasicMessageChannelDemo {
    var channel:FlutterBasicMessageChannel
    var count =  0
    init(messenger: FlutterBinaryMessenger) {
        channel = FlutterBasicMessageChannel(name: "com.flutter.guide.BasicMessageChannel", binaryMessenger: messenger)
        channel.setMessageHandler { (message, reply) in
            if let dict = message as? Dictionary<String, Any> {
                let name:String = dict["name"] as? String ?? ""
                let age:Int = dict["age"] as? Int ?? -1
                reply(["name":"hello,\(name)","age":age])
            }
        }
        startTimer()
    }
    func startTimer() {
        var timer = Timer.scheduledTimer(timeInterval:1, target: self, selector:#selector(self.tickDown),userInfo:nil,repeats: true)
    }
    @objc func tickDown(){
        count += 1
        var args = ["count":count]
        channel.sendMessage(args) { (reply) in
        }
    }
}

交流
老孟Flutter博客(330个控件用法+实战入门系列文章):http://laomengit.com
欢迎加入Flutter交流群(微信:laomengit)、关注公众号【老孟Flutter】:
![]()  | 
![]()  | 
【Flutter 混合开发】与原生通信-BasicMessageChannel的更多相关文章
- 【Flutter 混合开发】与原生通信-MethodChannel
		
Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...
 - 【Flutter 混合开发】与原生通信-EventChannel
		
Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...
 - 【Flutter 混合开发】嵌入原生View-Android
		
Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-IOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...
 - 【Flutter 混合开发】嵌入原生View-iOS
		
Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...
 - 【Flutter 混合开发】添加 Flutter 到 Android Activity
		
Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...
 - 【Flutter 混合开发】添加 Flutter 到 Android Fragment
		
Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...
 - 【Flutter 混合开发】添加 Flutter 到 iOS
		
Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...
 - flutter 混合开发
		
flutter 混合开发 https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps https://flutter.de ...
 - APP手机商城系统选择,混合开发与原生开发哪个好?
		
关于手机APP开发用混合还是原生现在说法不一,有说混合开发好:时间短.费用低.效果也不错,有说原生开发好,原生APP在性能方面比较好.而商城系统中的手机APP用混合开发还是原生开发比较好呢? 最近我参 ...
 
随机推荐
- 阿里云服务器外网IP无法访问网站
			
1.添加IIS时添加了127.0.0.1的IP监听导致无法访问外网IP 添加IP监听:netsh http add iplisten 127.0.0.1显示IP监听:netsh http show i ...
 - vue项目初始化自定义webpack与eslint
			
文章目录 问题 简化步骤 问题 // main.js import Antd from "ant-design-vue"; import "ant-design-vue/ ...
 - python语句与函数
			
赋值语句 : 分支语句 : 函数 :根据输入参数产生不同输出功能 程序的输入与输出 input() 从控制台获得用户输入的函数 使用格式 print()函数 以字符形式向控制台输出结果的函数 字符类型 ...
 - netty字符串流分包
			
@Override protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Obj ...
 - breakpad系列(2)——在Linux中使用breakpad
			
本文来自breakpad源码目录中doc目录下的linux_starter_guide.md,建议直接去看原文. 如何将breakpad添加进你的Linux程序 本文档是在Linux上使用Breakp ...
 - 带你搭建一个简单的mybatis项目:IDEA+spring+springMVC+mybatis+Mysql
			
最近小编有点闲,突发奇想想重温一下mybatis,然后在脑海中搜索了一下,纳尼,居然不太会用了,想到这里都是泪啊!!现在我所呆的的公司使用的是springboot+hebinate,编程都是使用的JP ...
 - java进阶(23)--List接口
			
一.基本概念 1.有序可重复 2.有下标 3.包含ArraList.LinkedList.Vector 二.List中特有的方法 且常用 (以下军均为数组通用方法) 1.void add(int ...
 - VS2017 Xamarin开发Android时首次部署完成后直接闪退
			
项目属性切换到Android选项,在打包属性上有一个[使用共享运行时]的选项要取消勾选,默认打钩时apk文件比较小,但程序无法运行起来. 取消后安装包一小变成几十M,这个目前好像没什么好的解决办法,毕 ...
 - 在KEIL下查看单片机编程内存使用情况
			
原文链接:https://blog.csdn.net/D_azzle/article/details/83410141 截至到目前为止,本人接触单片机也有将近一年的时间.这一年以来也接触过了很具代表性 ...
 - Python字符编码和二进制不得不说的故事
			
二进制 核心思想: 冯诺依曼 + 图灵机 电如何表示状态,才能稳定? 计算机开始设计的时候并不是考虑简单,而是考虑能自动完成任务与结果的可靠性, 简单始终是建立再稳定.可靠基础上 经过尝试10进制,但 ...
 
			
		
