flutter: 深入通信-发送端
环境: flutter sdk v1.5.4-hotfix.1@stable
对应 flutter engine: 52c7a1e849a170be4b2b2fe34142ca2c0a6fea1f
站在平台端的视角对通道有一个通观概览的认知之后就需要深入内里对通信机制需要一个深入剖析了,之前已经了解到FlutterJNI.dispatchPlatformMessage
是平台层(java)发送数据调用的最后一层,那么继续这个调用序列:
FluttereJNI.dispatchPlatformMessage nativeDispatchPlatformMessage(FlutterJNI.java) DispatchPlatformMessage(platform_view_android_jni.cc:56) AndroidShellHolder::GetPlatformView(platform_view_android_jni.cc:421) PlatformViewAndroid::DispatchPlatformMessage(platform_view_android.cc:92) TaskRunners::GetPlatformTaskRunner => PlatformView::task_runners_ new PlatformMessageResponseAndroid() new flutter::PlatformMessage(name, message, response) PlatformView::DispatchPlatformMessage PlatformView::Delegate::OnPlatformViewDispatchPlatformMessage() => Shell::On..() ::GetUITaskRunner TaskRunner::PostTask ...Engine::DispatchPlatformMessage
发送消息最终调用到了C++层的PlatformViewAndroid::DispatchPlatformMessage
方法, 又调用了PlatformViewAndroid
成员delegate_
的OnPlatformViewDispatchPlatformMessage
方法, 所以我们要确定PlatformView::Delegate
抽象类的实现体, 也就是要追踪成员被创建或赋值的地方。
由构造函数可知成员PlatformView::delegate_
是创建时外部传入,而PlatformViewAndroid
作为子类把它的delegate传入,所以需要了解PlatformViewAndroid
被创建时传入的delegate对象,
android_shell_holder.cc:63
可知创建PlatformViewAndroid
时传入的的delegate对象实际为Shell
,在其方法中又异步调用了成员engine_
的方法,即Engine::DispatchPlatformMessage
方法
所以我们需要
- 明确
PlatformViewAndroid
被创建的流程 - 明确
Engine
被赋值或创建的时机
创建PlatformViewAndroid
流程:
AndroidShellHolder::AndroidShellHolder() ThreadHost::ThreadHost platform_thread= fml::MessageLoop::EnsureInitializedForCurrentThread platform_runner=fml::MessageLoop::GetCurrent().GetTaskRunner() Shell::Create() DartVMRef::Create(settings) Shell::Create() TaskRunner::RunNowOrPostTask lamda() => Shell::CreateShellOnPlatformThread() Shell::CreateCallback<PlatformView>(Shell&) => on_create_platform_view new PlatformViewAndroid(Shell,...)
最重要的是Shell::Create
这个方法,在调用时传入了一个回调,这个回调调用了Shell::CreateShellOnPlatformThread()
, 继续回调了on_create_platform_view
,它的实现体在AndroidShellHolder
构造函数上下文中。
创建Shell::engine_[Engine]流程:
第二个问题刚好承接了对每一个问题的分析: 我们是在创建Shell
的时候创建了PlatformViewAndroid
对象shell.cc:38
可知engine_
也是外部传入
Shell::CreateShellOnPlatformThread() new Shell() on_create_platform_view => AndroidShellHolder.on_create_platform_view std::make_unique<PlatformViewAndroid>() TaskRunner::RunNowOrPostTask ...lamda => engine = std::make_unique<Engine>() (shell.cc:131) Shell::Setup engine_ = std::move(engine); (shell.cc:388)
在Shell::CreateShellOnPlatformThread
中先创建了Shell
实例, 接着创建了PlatformView
实例,接着又异步执行了一个lamda,创建了Engine
实例
这样前面两个重要对象的创建时机问题就终于明确了。
继续我们第一阶段的调用分析, 异步执行了Engine::DispatchPlatformMessage
Engine::DispatchPlatformMessage RuntimeController::DispatchPlatformMessage Window::DispatchPlatformMessage tonic::DartInvokeField(...,"_dispatchPlatformMessage")
最终由此进行到了Dart层调用
因为在AndroidShellHolder
的构造函数中Flutter创建了Shell
对象,所以同样需要明确:
创建AndroidShellHolder
流程:
FlutterActivity.onCreate (FlutterActivity.java:89) FlutterActivityDelegate.onCreate() (FlutterActivityDelegate.java:160) FlutterView.FlutterView() (FlutterView.java:139) new FlutterNativeView(Context) (FlutterNativeView.java:47) FlutterNativeView.attach(this, false) (FlutterNativeView.java:165) FlutterJNI.attachToNative (FlutterJNI.java:423) AttachJNI(platform_view_android_jni.cc:149) java_object(env, flutterJNI) std::make_unique<AndroidShellHolder>(java_object) AndroidShellHolder::IsValid reinterpret_cast<jlong>
比较容易发现创建的时机正是FlutterJNI
绑定到FlutterNativeView
, 而FlutterJNI
的成员nativePlatformViewId
代表的正是C++AndroidShellHolder
对象,在这个过程中重要对象如Shell
和Engine
相继被创建。
所以每次发送数据(或者平台调用dart方法)都是FlutterJNI
对象将成员nativePlatformViewId
传入c++层,转成AndroidShellHolder
对象通过Engine
最终调用到dart层