资讯专栏INFORMATION COLUMN

Channel: flutter平台层与运行层的双向通信

BetaRabbit / 1110人阅读

摘要:环境对应存在这样的情形应用的视图控件响应用户的输入比如需要将平台的按键数据传递到的环境并响应同时应用可能因为某个操作需要调用平台的接口让手机震动但是的视图运行代码平台运行代码同时层无法识别层定义的对象类这就需要将数据在不同的运行环境中传递

环境: flutter sdk v1.5.4-hotfix.1@stable

对应 flutter engine: 52c7a1e849a170be4b2b2fe34142ca2c0a6fea1f

存在这样的情形: flutter应用的视图控件响应用户的输入(比如KeyEvent), 需要将平台的按键数据传递到flutter的dart环境并响应, 同时应用可能因为某个操作需要调用平台的接口让手机震动. 但是flutter的App视图运行dart代码,平台(Android)运行Java代码, 同时dart层无法识别java层定义的对象类, 这就需要将数据在不同的运行环境中传递, flutter框架中的channel机制其实就是实现这个目的的.

一些文章和部分代码可能会让人感到困扰, 为什么已经有send接口了还要添加一个setMessageHander接口, 同时send已经有回调reply了, 怎么MessageHandler除了数据还有带一个reply.

理解的关键其实就是这个channel, 顾名思义, 就是进行数据传送的通道, 在平台层(java)与运行层(dart)进行数据通信. 一旦涉及通信就涉及对象传递, 而在不同运行时(runtime)环境进行对象传递就必然涉及对象序列化了. 所以不用被名称迷惑, 所谓的MessageCodec其实就是专门作对象序列化的实例, 而通道既然能发送数据也必须能够接收数据, 如此的双向通信, 仅此而已.

一个通道关联3个对象: 名称, 操作与序列化, 操作即具体做收发消息的工作, 即Messenger. 而消息按类型又分为普通对象, 操作方法, 数据流, 对应着3种基本通道: BasicMessageChannel, MethodChannel, EventChannel

发送有时机, 接收无定时

平台端(android)可以显式的创建一个通道, 通道建立后既可作为发送端又可作为接收端, 作为发送端可以主动的传送相关数据, 是为有时机, 作为接收端, 只能被动等待数据到来, 是为无定时

数据发送

调用一个通道的send方法,即为发送数据了, 有时发送完数据需要一个反馈, 于是有另一个回调参数Reply, 这个回复是接收端反馈给发送端后发送端作的响应, 可以叫做发送回复.

数据接收

每种通道都设置了一个setMessageHandler的方法, MessageHandler其实就是通道的数据接收器, 更容易理解的名字应该是MessageReceiver, 专门等待发送端发送的数据; 表示通道建立后作为接收方接收数据后进行的处理, 数据处理完之后可能需要再反馈给发送端, 所以MessageHandler.onMessage(T message, Reply reply)中的Reply是接收端反馈给发送端的回复, 可以叫做接收回复

通道解码

理解了通道本质, 通道的解码MessageCodec就显而易见了, 也就显得不那么重要了: 在数据通信过程中针对各种各样的数据对象进行序列化和反序列化. 我们自己也完全可以定制自己的序列方式(比如gson), 因为无论是c++层java层还是dart层, 只能读写字节.

可以总结如下:
通道的本质即数据通信
通道的解码即对数据进行序列化和反序列化
通道可作为发送端也可作为接收端
通道最终是以二进制字节的形态传送数据
c++消弥平台的差异(android,ios), 同时提供统一的接口和方式供dart使用

数据发送示例

普通对象传递-以Android端传递按键事件至dart端为例
按键数据被包装成一个对象实例,通道对象类型是BinaryMessenger调用序列如下:

FlutterView.onKeyDown
  AndroidKeyProcessor.onKeyDown
    KeyEventChannel.keyDown
     BasicMessageChannel.send
       BinaryMessenger.send -> DartExecutor.send
         DartMessenger.send
           FlutterJNI.dispatchPlatformMessage

最终调用了BinaryMessenger的send方法, 其实现体是DartExecutor, DartExecutor是平台层与运行层交互的点, 它实现了平台向dart调用, dart向平台的响应.

调用dart方法-以Android端传递导航事件至dart端为例
activity响应打开页面的方法onNewIntent被flutter定义了一个导航方法,通道对象类型是MethodChannel, 调用序列如下:

FlutterActivityDelegate.onNewIntent
  FlutterActivityDelegate.loadIntent
    FlutterView.setInitialRoute
      NavigationChannel.setInitialRoute
        MethodChannel.invokeMethod
          new MethodCall
          JSONMethodCodec.encodeMethodCall
          BinaryMessenger.send -> DartExecutor.send
            DartMessenger.send
              FlutterJNI.dispatchPlatformMessage

可以看到方法的名称与参数被包装成了MethodCall, 结构体被序列化成了字节之后传递给dart, 最终还是调用了DartMessenger的send方法

此外还有EventChannel,但是在代码中没有实例化(2019.06.24 flutter-engine:52c7a1e8)就先不分析了,本质与原理还是一样的。

响应发送回复

可以看到DartMessengerpendingReplies:Map<>缓存了BinaryMessenger.BinaryReply, 待dart代码执行完发送端操作后响应handlePlatformMessageResponse时取出, 完成发送反馈, 在MethodChannel中即为方法返回值.

数据接收示例

接收dart层通知
目前代码中只有AccessibilityChannel有用到BasicMessageChannel.MessageHandler, 这是为了设置android视图ViewAccessibility属性, 平常开发不怎么用到, 但毫无疑问,最终调用的还是平台层的相关代码

接收dart层调用-以Android端调用平台类PlatformChannel为例
PlatformChannel负责dart层向平台层调用的统一操作, 其创建过程如下

FlutterView.FltterView()
  new PlatformChannel
    new MethodChannel
    MethodChannel.setMethodCallHandler
      BinaryMessenger.setMessageHandler -> DartExecutor.setMessageHandler
        DartMessenger.setMessageHandler
  new PlatformPlugin
    PlatformChannel.setPlatformMessageHandler

DartMessengermessageHandlers根据通道名称缓存了BinaryMessenger.BinaryMessageHandler, 平台层作为接收方不定时等待dart层发送数据, 方法调用流程如下:

DartMessenger.handleMessageFromDart
  BinaryMessenger.BinaryMessageHandler.onMessage -> MethodChannel.IncomingMethodCallHandler.onMessage
    MethodCallHandler.onMethodCall -> PlatformChannel.parsingMethodCallHandler.onMethodCall
      PlatformMessageHandler.vibrateHapticFeedback -> PlatformPlugin.mPlatformMessageHandler.vibrateHapticFeedback
        PlatformPlugin.vibrateHapticFeedback
          View.performHapticFeedback

由上可见DartMessenger是channel机制中最为重要的核心类, 是在平台层负责与运行层通信的最关键角色.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/15025.html

相关文章

  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?

    摘要:中国互联网络信息中心发布的中国互联网络发展状况统计报告显示,截至年月,我国网民规模达亿人,微信月活亿支付宝月活亿百度月活亿另一方面,中国手机占智能手机整体的比例超过,月活约亿。在年末正式发布了面向未来的跨端的。 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的? 原创: 嘉宾-张楠 开源中国 以往我们说某一功能跨多端,往往是指在诸如 PC、移动等不同类型的设备之...

    GraphQuery 评论0 收藏0
  • Flutter 面试知识点集锦

    摘要:中的的线程是以事件循环和消息队列的形式存在,包含两个任务队列,一个是内部队列,一个是外部队列,而的优先级又高于。同时还有处理按住时的事件额外处理,同时手势处理一般在的子类进行。谷歌大会之后,有不少人咨询了我 Flutter 相关的问题,其中有不少是和面试相关的,如今一些招聘上也开始罗列 Flutter 相关要求,最后想了想还是写一期总结吧,也算是 Flutter 的阶段复习。 ⚠️系统完...

    andong777 评论0 收藏0
  • 平台技术演进

    摘要:接下来,我将从原理优缺点等方面为大家分享跨平台技术演进。小程序年是微信小程序飞速发展的一年,年,各大厂商快速跟进,已经有了很大的影响力。下面,我们以微信小程序为例,分析小程序的技术架构。 前言 大家好,我是simbawu ,@BooheeFE Team Leader,关于这篇文章,有问题欢迎来这里讨论。 随着移动互联网的普及和快速发展,手机成了互联网行业最大的流量分发入口。以及随着5G...

    魏宪会 评论0 收藏0
  • 平台技术演进

    摘要:接下来,我将从原理优缺点等方面为大家分享跨平台技术演进。小程序年是微信小程序飞速发展的一年,年,各大厂商快速跟进,已经有了很大的影响力。下面,我们以微信小程序为例,分析小程序的技术架构。 前言 大家好,我是simbawu ,@BooheeFE Team Leader,关于这篇文章,有问题欢迎来这里讨论。 随着移动互联网的普及和快速发展,手机成了互联网行业最大的流量分发入口。以及随着5G...

    MasonEast 评论0 收藏0
  • 平台技术演进

    摘要:接下来,我将从原理优缺点等方面为大家分享跨平台技术演进。小程序年是微信小程序飞速发展的一年,年,各大厂商快速跟进,已经有了很大的影响力。下面,我们以微信小程序为例,分析小程序的技术架构。 前言 大家好,我是simbawu ,@BooheeFE Team Leader,关于这篇文章,有问题欢迎来这里讨论。 随着移动互联网的普及和快速发展,手机成了互联网行业最大的流量分发入口。以及随着5G...

    fasss 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<