flutter
是啥就不介绍了。。。这篇主要针对flutter channel,不涉及dart::ffi。主要是dart<->c++<->java的通信。
核心概念
- BinaryMessenger:真正的信道,用来传输数据的
- MethodCall:传输的数据内容,event和method都被认为是MethodCall
- MessageCodec:用来序列化/反序列化数据
方法定义和绑定
所有的绑定都是在BinaryMessenger中,由于跨语言,所以实际代码是c++的。注意,只有setMethodHandler之后才算注册上了方法,只invoke并不会有注册。只关注defaultBinaryMessager(ServicesBinding.instance.defaultBinaryMessenger)
信道建立
dart侧
runApp->new WidgetsFlutterBinding->ServicesBinding#initInstances。
构建_DefaultBinaryMessenger,并将_DefaultBinaryMessenger#handlePlatformMessage赋值给Window#onPlatformMessage。
java侧
new FlutterEngine->new DartExecutor->new DartMessenger->DartExecutor#onAttachedToJNI->FlutterJNI#setPlatformMessageHandler(存到FlutterJNI上)
library_loader.cc->PlatformViewAndroid#Register->platform_view_android_jni_impl#Register->绑定FlutterJNI#handlePlatformMessage到native
方法声明
dart回调以channelName->function的形式存到了_DefaultBinaryMessenger中。
java回调以channelName->MethodCallHandler的形式存到了DartMessenger中。
dart call java
- 构造MethodCall->StandardMethodCodec#encodeMethodCall ->构建WriteBuffer->StandardMessageCodec#writeValue。序列化后是个ByteData/Unit8List(内容是TLV),以bootstrap_natives.h的形式绑定到了c++。
- _DefaultBinaryMessenger#send->_DefaultBinaryMessenger#_sendPlatformMessage->ui.Window#sendPlatformMessage->window.cc#SendPlatformMessage。
- 前文提到的ByteData会在DartVM中直接解包出来bytes。new DartByteData->Dart_TypedDataAcquireData->Api::UnwrapTypedDataHandle。这里会直接把native对象作为数据强转。
- 如果没理解错,TypedData一系列逻辑是直接通过native关键字将dart对象和native对象地址绑定到一起(typed_data_patch.dart、bootstrap_natives.cc中的宏)。然后把所有的dart方法以library#set_native_entry_symbol_resolver(Bootstrap#SetupNativeResolver)的方法转交给native 宏中生成的方法。
- 接上文->Engine#HandlePlatformMessage->Shell#OnEngineHandlePlatformMessage->切到android主线程PlatformViewAndroid#HandlePlatformMessage,生成response handle并关联到自增id上->PlatformViewAndroidJNIImpl#FlutterViewHandlePlatformMessage->FlutterJNI.java#handlePlatformMessage->一路走到IncomingMethodCallHandler#onMessage(这里decode)。
- reply过程:Reply#reply(这里encode)->FlutterJNI#invokePlatformMessageResponseCallback->platform_view_android_jni_impl->PlatformViewAndroid#InvokePlatformMessageResponseCallback(根据之前生成的自增id找到callback并回调,这个回调直接封装了dart handle,所以可以理解为切换线程并直接调到了dart)
java call dart
基本就是上述过程反过来,不赘述。
类型约束及传输
约束见官方文档。
整体看,数据从原始对象直接填充到c++的bytes里,仅在把数据转换为语言对象时才有额外内存申请,内存是传输数据原始大小的三倍。
传输过程重点是序列化后的数据全部都集中到c++侧(DirectBuffer@java和ByteData@dart),利用vm的api进行interpo,避免过多数据拷贝。但是,数据仍然是以序列化(copy+1)->bytes->反序列化(copy+1,释放bytes)的方式进行,所以有相当规模的拷贝。