一、简介
PlatformChannel是Flutter端与Platform端制定的通信机制,由官方提供用于Dart和平台之间的相互通信。
分为以下3种
(1)BaseMessageChannel:用于传递字符串和半结构化的信息(在大内存数据块传递的情况下使用)
(2)MethodChannel:用于传递方法调用(MethodInvocation)
(3)EventChannel:用于数据流(EventStreams)的通信
二、消息传递与编码器
Flutter的消息传递工具是BinaryMessager,通过它与Platform建立起通信关系,消息以二进制的格式进行传递。
如图所示BinaryMessager的传递需要经过BinaryMessageHandler,BinaryMessagerHandler是以ChannelName作为键值生成出来再被注册到BinaryMessager上的,BinaryMessageHandler和BinaryMessager是一一对应的,二进制格式的消息通过消息编码器(Codec)解码为可识别的信息,并传递给Handler进行处理。Handler处理完后,会把结果编码为二进制格式,再通过回调函数返回结果并发送回Flutter端。
1.编码器分类
(1)MessageCodec:BinaryCodec、StringCodec、JSONMessageCodec、StandardMessageCodec
(2)MethodCodec:JSONMethodCodec、StandardMessageCodec
经过消息编码器处理后,消息就可以被Handler进行处理了。
2.消息编码过程
Android端的返回值是java.lang.Integer类型的,而iOS端返回值则是一个NSNumber类型的(通过NSNumbernumberWithInt:获取)。而到了Flutter端时,这个返回值自动“变成”了Dart语言的Int类型。
standardplatformchannels使用standardmesssagecodec对message和response进行序列化和反序列化,message与response可以是booleans,numbers,Strings,bytebuffers,List,Maps等等,而序列化后得到的则是二进制格式的数据。
Flutter默认的消息编码器是StandardMessageCodec,支持的数据类型如下:
三、MethodChannel
MethodChannel是Flutter与Platform之间传递信息的一种,其传递过程是:BinaryMessagerBinaryMessagerHandlerMethodChannel。
如上图:Native端(iOS和Android)为宿主端(host),Flutter则是客户端(client),Flutter调用Native方法时,需要传递的信息是通过平台通道传递到宿主端的,Native收到调用的信息后方可执行指定的操作。如有返回的数据,则Native会将数据再通过平台通道一并传递给Flutter,其中数据传递是异步的,这样就能确保消息传递时用户界面不会被阻塞。
1.Flutter层(Dart层)
Flutter端使用MethodChannel的invokeMethod方法发起一次方法调用时,开始了消息传递流程。invokeMethod方法会将其入参message和arguments封装成一个MethodCall对象,并使用MethodCodec将其编码为二进制格式数据,再通过BinaryMessages将消息发出。(注意,此处提到的类名与方法名均为Dart层的实现)
上述过程最终会调用到ui.Window的_sendPlatformMessage方法,该方法是一个Native方法,其实现在Native层,这与Java的JNI技术非常类似。我们向Native层发送了三个参数:
name,String类型,代表Channel名称
data,ByteData类型,即之前封装的二进制数据
callback,Function类型,用于结果回调
2.Native层
到Native层后,window.cc的SendPlatformMessage方法接受了来自Dart层的三个参数,并对它们做了一定的处理:Dart层的回调callback封装为Native层的PlatformMessageResponseDart类型的response;dart层的二进制数据data转化为std::vectoruint8t类型数据data;根据response,data以及Channel名称name创建一个PlatformMessage对象,并通过dartstate-window()-client()-HandlePlatformMessage方法处理PlatformMessage对象。
dart_state-window()-client()是一个WindowClient,而其具体的实现为RuntimeController,RuntimeController会将消息交给其代理RuntimeDelegate处理。
RuntimeDelegate的实现为Engine,Engine在处理Message时,会判断该消息是否是为了获取资源(channel等于flutter/assets),如果是,则走获取资源逻辑,否则调用Engine::Delegate的OnEngineHandlePlatformMessage方法。
Engine::Delegate的具体实现为Shell,其OnEngineHandlePlatformMessage接收到消息后,会向PlatformTaskRunner添加一个Task,该Task会调用PlatformView的HandlePlatformMessage方法。值得注意的是,Task中的代码执行在PlatformTaskRunner中,而之前的代码均执行在UITaskRunner中。
四、消息处理
PlatformView的HandlePlatformMessage方法在不同平台有不同的实现,但是其基本原理是相同的。
1.PlatformView
AndroidPlatformViewAndroid是Platformview的子类,也是其在Android端的具体实现。当PlatformViewAndroid接收到PlatformMessage类型的消息时,如果消息中有response(类型为PlatformMessageResponseDart),则生成一个自增长的responseid,并以responseid为key,response为value存入字典pendingresponses中。接着,将channel和data均转化为Java可识别的数据,通过JNI向Java层发起调用,将response_id、channel和data传递过去。
Java层中,被调用的代码为FlutterNativeView(BinaryMessager的具体实现)的handlePlatformMessage,该方法会根据channel找到对应的BinaryMessageHandler并将消息传递给它处理。
BinaryMessageHandler处理完成后,FlutterNativeView会通过JNI调用native的方法,将responsedata和responseid传递到native层。
Native层,PlatformViewAndroid的InvokePlatformMessageResponseCallback接收到了respondid和responsedata。其先将responsedata转化为二进制结果,并根据responseid,从pandingresponses中找到对应的PlatformMessageResponseDart对象,调用其Complete方法将二进制结果返回。
2.PlatformViewIOS
PlatformViewIOS是PlatformView的子类,也是其在iOS端的具体实现,当PlatformViewIOS接收到message时会交给PlatformMessageRouter处理。
PlatformMessageRouter通过PlatformMessage中的channel找到对应的FlutterBinaryMessageHandler,并将二进制消息其处理,消息处理完成后,直接调用PlatformMessage对象中的PlatformMessageResponseDart对象的Complete方法将二进制结果返回。
3.结果回传
PlatformMessageResponseDart的Complete方法向UITaskRunner添加了一个新的Task,这个Task的作用是将二进制结果从native的二进制数据类型转化为Dart的二进制数据类型response,并调用Dart的callback将response传递到Dart层。
Dart层接收到二进制数据后,使用MethodCodec将数据解码,并返回给业务层。至此,一次从Flutter发起的方法调用就完整结束了。
五、具体使用
1.Flutter端调用Android方法
2.Android端代码
(1)继承MethodCallHandler并设置Handler,MethodChannel需要保存在对象一会调用回调时需要使用,onMethodCall为Flutter层回调的方法这边用RCIMFlutterWrapper承接处理。
(2)RCIMFlutterWrapper类中处理,MethodCall的Method,对应Flutter层调用invokeMethod方法的传入的第一个参数,两端需完全对应一致。
(3)直接通过result对象回调回去,这样就能将结果回调。
3.关于Android回调Flutter的使用
(1)Flutter端回调监听,设置监听Key两端对应。
(2)Android端代码回调,mChannel.invokeMethod方法将数据回调给Flutter层。
转载请注明:http://www.0431gb208.com/sjszlff/4609.html