環境: flutter sdk v1.5.4-hotfix.1@stable
對應 flutter engine: 52c7a1e849a170be4b2b2fe34142ca2c0a6fea1fjava
站在平臺端的視角對通道有一個通觀概覽的認知以後就須要深刻內裏對通訊機制須要一個深刻剖析了,以前已經瞭解到FlutterJNI.dispatchPlatformMessage
是平臺層(java)發送數據調用的最後一層,那麼繼續這個調用序列:android
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
抽象類的實現體, 也就是要追蹤成員被建立或賦值的地方。c++
由構造函數可知成員PlatformView::delegate_
是建立時外部傳入,而PlatformViewAndroid
做爲子類把它的delegate傳入,因此須要瞭解
PlatformViewAndroid
被建立時傳入的delegate對象,git
android_shell_holder.cc:63
可知建立PlatformViewAndroid
時傳入的的delegate對象實際爲Shell
,在其方法中又異步調用了成員engine_
的方法,即Engine::DispatchPlatformMessage
方法github
因此咱們須要shell
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
的時候建立了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
實例oop
這樣前面兩個重要對象的建立時機問題就終於明確了。this
繼續咱們第一階段的調用分析, 異步執行了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層