flutter: 深刻通訊-發送端

環境: 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

  1. 明確PlatformViewAndroid被建立的流程
  2. 明確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實例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對象,在這個過程當中重要對象如ShellEngine相繼被建立。
因此每次發送數據(或者平臺調用dart方法)都是FlutterJNI對象將成員nativePlatformViewId傳入c++層,轉成AndroidShellHolder對象經過Engine最終調用到dart層

相關文章
相關標籤/搜索