环境: flutter sdk v1.5.4-hotfix.1@stablejava
对应 flutter engine: 52c7a1e849a170be4b2b2fe34142ca2c0a6fea1fandroid
存在这样的情形: flutter应用的视图控件响应用户的输入(好比KeyEvent), 须要将平台的按键数据传递到flutter的dart环境并响应, 同时应用可能由于某个操做须要调用平台的接口让手机震动. 可是flutter的App视图运行dart代码,平台(Android)运行Java代码, 同时dart层没法识别java层定义的对象类, 这就须要将数据在不一样的运行环境中传递, flutter框架中的channel机制其实就是实现这个目的的.ios
一些文章和部分代码可能会让人感到困扰, 为何已经有send接口了还要添加一个setMessageHander接口, 同时send已经有回调reply了, 怎么MessageHandler除了数据还有带一个reply.c++
理解的关键其实就是这个channel, 顾名思义, 就是进行数据传送的通道, 在平台层(java)与运行层(dart)进行数据通讯. 一旦涉及通讯就涉及对象传递, 而在不一样运行时(runtime)环境进行对象传递就必然涉及对象序列化了. 因此不用被名称迷惑, 所谓的MessageCodec
其实就是专门做对象序列化的实例, 而通道既然能发送数据也必须可以接收数据, 如此的双向通讯, 仅此而已.git
一个通道关联3个对象: 名称, 操做与序列化, 操做即具体作收发消息的工做, 即Messenger
. 而消息按类型又分为普通对象, 操做方法, 数据流, 对应着3种基本通道: BasicMessageChannel<T>, MethodChannel, EventChannel
github
平台端(android)能够显式的建立一个通道, 通道创建后既可做为发送端又可做为接收端, 做为发送端能够主动的传送相关数据, 是为有时机, 做为接收端, 只能被动等待数据到来, 是为无定时缓存
调用一个通道的send方法,即为发送数据了, 有时发送完数据须要一个反馈, 因而有另外一个回调参数Reply<T>
, 这个回复是接收端反馈给发送端后发送端做的响应, 能够叫作发送回复.bash
每种通道都设置了一个setMessageHandler
的方法, MessageHandler<T>
其实就是通道的数据接收器, 更容易理解的名字应该是MessageReceiver
, 专门等待发送端发送的数据; 表示通道创建后做为接收方接收数据后进行的处理, 数据处理完以后可能须要再反馈给发送端, 因此MessageHandler<T>.onMessage(T message, Reply<T> reply)
中的Reply<T>
是接收端反馈给发送端的回复, 能够叫作接收回复框架
理解了通道本质, 通道的解码MessageCodec
就显而易见了, 也就显得不那么重要了: 在数据通讯过程当中针对各类各样的数据对象进行序列化和反序列化. 咱们本身也彻底能够定制本身的序列方式(好比gson), 由于不管是c++层java层仍是dart层, 只能读写字节.spa
能够总结以下:
通道的本质即数据通讯
通道的解码即对数据进行序列化和反序列化
通道可做为发送端也可做为接收端
通道最终是以二进制字节的形态传送数据
c++消弥平台的差别(android,ios), 同时提供统一的接口和方式供dart使用
普通对象传递-以Android端传递按键事件至dart端为例
按键数据被包装成一个对象实例,通道对象类型是BinaryMessenger<Object>
调用序列以下:
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)就先不分析了,本质与原理仍是同样的。
能够看到DartMessenger
用pendingReplies:Map<>
缓存了BinaryMessenger.BinaryReply
, 待dart代码执行完发送端操做后响应handlePlatformMessageResponse
时取出, 完成发送反馈, 在MethodChannel
中即为方法返回值.
接收dart层通知
目前代码中只有AccessibilityChannel
有用到BasicMessageChannel.MessageHandler
, 这是为了设置android视图View
的Accessibility
属性, 日常开发不怎么用到, 但毫无疑问,最终调用的仍是平台层的相关代码
接收dart层调用-以Android端调用平台类PlatformChannel为例
PlatformChannel
负责dart层向平台层调用的统一操做, 其建立过程以下
FlutterView.FltterView()
new PlatformChannel
new MethodChannel
MethodChannel.setMethodCallHandler
BinaryMessenger.setMessageHandler -> DartExecutor.setMessageHandler
DartMessenger.setMessageHandler
new PlatformPlugin
PlatformChannel.setPlatformMessageHandler
复制代码
DartMessenger
用messageHandlers
根据通道名称缓存了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机制中最为重要的核心类, 是在平台层负责与运行层通讯的最关键角色.