Flutter与Native通信原理剖析与实践

2023-09-14 04:41:34

通信原理

我们分几种场景来介绍Flutter和Native之间的通信。

  • Native发送数据给Flutter
  • Flutter发送数据给Native
  • Flutter发送数据给Native,然后Native回传数据给Flutter

在这里插入图片描述

Flutter与Native通信机制

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

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

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

在这里插入图片描述

  • Flutter定义了三种不同类型的Channel:
    1. BasicMessageChannel:用于传递字符串和半结构化的信息,持续通信,收到消息后可以回复此次消息,如:Native将遍历到的文件信息陆续传递到Flutter,在比如:Flutter将从服务端陆陆续续获取到信息交给Native加工,Native处理完返回等;
    2. MessageChannel:用于传递方法调用,一次性通信:如Flutter调用Native拍照;
    3. EventChannel:用于数据流的通信,持续通信,通常用于Native向Flutter的通信,如:手机电量变化,网络连接变化等;

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

通信原理

在这里插入图片描述

  • 无论是哪一种类型的Channel,它能和Flutter进行通信主要是借助BinaryMessenger来实现的。
  • 三种类型的Channel在Flutter侧都有对应的实现。

实践

  • flutter主动发送数据给native,native接受到消息后回信给flutter
    1. Android端
class MainActivity : FlutterActivity() {

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        val channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "HiFlutterBridge")//HiFlutterBridge需要和flutter端的对应

        channel.setMethodCallHandler { call, result ->
            Log.e("HiFlutterBridge", "argus is ${call.arguments}")
            if (call.method == "goToNative") {
                val data = "Hello from native!"
                result.success(data)
            } else {
                result.notImplemented()
            }
        }
    }
  1. Flutter端
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';

class HiFlutterBridge {
  static HiFlutterBridge _instance = HiFlutterBridge._();
  final MethodChannel _bridge = const MethodChannel("HiFlutterBridge");//需要和原生端的MethodChannel方法的第二个参数一致
  var _listener = {};

  HiFlutterBridge._() {
    _bridge.setMethodCallHandler((MethodCall call) {
      String method = call.method;
      if (_listener[method] != null) {
        return _listener[method](call);
      }
      return Future(() => null);
    });
  }

  static HiFlutterBridge getInstance() {
    return _instance;
  }

  register(String method, Function(MethodCall) callBack) {
    _listener[method] = callBack;
  }

  unRegister(String method) {
    _listener.remove(method);
  }

  goToNative(Map params) async {
    String result = await _bridge.invokeMethod("goToNative", params);
    debugPrint("HiFlutterBridge result is $result");
  }

  MethodChannel bridge() {
    return _bridge;
  }
}

  
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
        resizeToAvoidBottomInset: false, // 设置为false以避免在打开软键盘时widget被顶上去
        body: HideKeyboard(
            child: Stack(
          children: <Widget>[
            Align(
              alignment: Alignment.center,
              child: ElevatedButton(
                onPressed: () => {
                  //flutter向native端通信

                  HiFlutterBridge.getInstance()
                      .goToNative({"test": "hello world"})
                },
                // style: ElevatedButton.styleFrom(
                //     minimumSize: const Size(100, 50),
                //     maximumSize: const Size(100, 50),
                //     shape:
                //     RoundedRectangleBorder(borderRadius: BorderRadius.circular(30))),
                child: const Text('login'),
              ),
            )
          ],
        )));
  }
  • native主动发送数据给flutter,flutter接受到消息后回信给native
    1. Android端
class MainActivity : FlutterActivity() {

    override fun onResume() {
        super.onResume()
        sendDataToFlutter()
    }

    private fun sendDataToFlutter() {
        val channel = MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, "test")
        channel.invokeMethod(" sendData ", "Hello Flutter", object : MethodChannel.Result {
            override fun success(o: Any?) {
                Log.d("Native", "Received back: " + o.toString())
            }

            override fun error(s: String, s1: String?, o: Any?) {
                Log.e("Native", "Error: $s1")
            }

            override fun notImplemented() {}
        })
    }
}
  1. Flutter端
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';

class HiFlutterBridge {
  static HiFlutterBridge _instance = HiFlutterBridge._();
  final MethodChannel _bridge = const MethodChannel("test");
  var _listener = {};

  HiFlutterBridge._() {
    _bridge.setMethodCallHandler((MethodCall call) async{
      debugPrint("test ===> ${call}");
      return "flutter ===> native";
      String method = call.method;
      if (_listener[method] != null) {
        return _listener[method](call);
      }
      return Future(() => null);
    });
  }

  static HiFlutterBridge getInstance() {
    return _instance;
  }

  register(String method, Function(MethodCall) callBack) {
    _listener[method] = callBack;
  }

  unRegister(String method) {
    _listener.remove(method);
  }

  goToNative(Map params) async {
    String result = await _bridge.invokeMethod("goToNative", params);
    debugPrint("HiFlutterBridge result is $result");
  }

  MethodChannel bridge() {
    return _bridge;
  }
}

  
  void initState() {
    // TODO: implement initState
    super.initState();
    HiFlutterBridge.getInstance();
  }
  • 运行结果
I/flutter (27181): test ===> MethodCall( sendData , Hello Flutter)
D/Native  (27181): Received back: flutter ===> native
更多推荐

加速老化测试目的是什么?

加速老化测试使用加速应力的组合来暴露产品设计和制造中的产品缺陷。这有助于提高产品可靠性并减少现场故障和保修费用。加速老化测试在环境室中进行,高温加速有效时间,通常与所有振动台结合使用,产生全轴振动。加速老化测试可分为高加速寿命测试(HALT)和高加速应力筛选(HASS)。这两种技术都使用远远超出产品正常工作条件的应力,

IT隔离电源系统在医院低压配电箱中的应用

【摘要】参考国外及国际对医疗领域的相应标准,结合我国有关的规范%标准,对手术室等处的供配电系统作出了探讨;论述了IT配电系统在医院的应用范围;分析了IT系统接地故障的特点;提出了医院手术室IT电源系统的基本配置。【关键词】手术室配电系统;故障;绝缘监视;漏电198.2138.07290引言*近,本院就北部分院的两百多个

mybatis动态sql&choose&foreach&sql 及include & sql中的特殊字符&后台分页实现& 数据版本号处理并发问题

1.动态sql简述mybatis的动态sql语句是基于OGNL表达式的。可以方便的在sql语句中实现某些逻辑.总体说来mybatis动态SQL语句主要有以下几类:if语句(简单的条件判断)choose(when,otherwize),相当于java语言中的switch,与jstl中的choose很类似trim(对包含的

【Python】基础数据结构:列表——元组——字典——集合

文章目录一、简述二、Python中的列表详解2.1创建列表2.2访问列表元素2.3修改列表元素2.4列表切片2.5列表方法2.6列表推导式三、Python中的元组详解3.1创建元组3.2访问元组元素3.3元组是不可变的3.4元组切片3.5元组方法四、Python中的字典详解4.1创建字典4.2访问字典元素4.3修改字典

IT隔离电源系统在医院电气设计中的应用

【摘要】许多国际标准都对医疗领域,尤其是那些生命攸关的场所,如手术室、重症监护室、心脏监护室等的配电系统作了特殊的规定。现在国际上针对医疗领域中的手术室、ICU、CCU等重要场所通常采用局部“中性点不接地的供电系统”(IEC标准称之为“医疗IT系统”或“隔离电源系统”)供电。文章阐述了IT系统设置的必要性,国内外规范的

机器学习实战:Python基于GBM梯度提升机进行预测(十四)

这篇干货很硬,喜欢的小伙伴点个赞/收藏,持续更新!文章目录1.前言1.1GBM的介绍1.2GBM的应用2.scikit-learn实战演示2.1分类问题2.2回归问题3.GBM超参数3.1决策树数量(n_estimators)3.2样本数量(subsample)3.3特征数量(max_features)3.4学习率(l

lv5 嵌入式开发-3 守护进程

目录1守护进程的概念1.1相关概念1.2举例1.3函数介绍2守护进程的实现2.1简单创建2.2守护进程创建2.3实例掌握:守护进程特点、会话、控制终端、创建守护进程1守护进程的概念守护进程又叫精灵进程(DaemonProcess),它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的

zabbix(一)

为什么需要监控?保证业务7*24小时,稳定运行小厂要求满足:99.9%大厂要求满足99.99%提前做监控,只要有问题立马报警,报警需要时间有时候出的故障,故障处理需要时间高可用性99.99%这个很难linux系统oomOutofmemorylinux内核杀掉程序进程,释放内存网速快,网页秒开网速慢,网页超时1M/s10

通讯网关软件008——利用CommGate X2Mysql实现OPC数据转储Mysql

本文介绍利用CommGateX2MYSQL实现从OPCServer读取数据并转储至MYSQL数据库。CommGateX2MYSQL是宁波科安网信开发的网关软件,软件可以登录到网信智汇(http://wangxinzhihui.com)下载。【案例】如下图所示,实现从OPCServer读取数据并转储至MYSQL数据库。【

企业诊断屋:二手车交易平台 APP 如何用 AB 测试赋能业务

更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群2023年汽车行业新车市场低靡,由新车降价引发的车辆价格波动很快传导到二手车市场,二手车的交易也受到了冲击,收车验车更加谨慎,诸多二手交易平台想要保障平台的交易率也变得竞争激烈。二手车交易平台需要吸引各方平台上交易,既要有卖家又要有买家

车辆OBD数据采集

OBD接口作为车载监控系统的通讯接口,除了读取故障码以供修车外,其首要功能就是可提供车辆的各种工况数据,如燃油压力、发动机空气流量和车速等。OBD接口可快速方便地监测公司车辆和竞争车辆的多个系统和部件,包括发动机、催化转化器、颗粒捕集器、氧传感器、4a4949排放控制系统、燃油系统和GER等,从而可直接获取多项车辆基本

热文推荐