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层

相关文章
相关标签/搜索