flutter: 深入通訊-接收端

林鹿發表於2019-07-02

環境: flutter sdk v1.5.4-hotfix.1@stable

對應 flutter engine: 52c7a1e849a170be4b2b2fe34142ca2c0a6fea1f

前言

通過PlatformChannel為平臺層作為接收端的例子我們已經瞭解到DartMessenger通過響應介面handleMessageFromDart來把Dart層的訊息/操作傳送到平臺層,而這個方法是PlatformMessageHandler這個介面物件的,持有介面例項的物件正是FlutterJNI

作為被動呼叫的一方,平臺層等待訊息接收,並不知道訊息的來源和用途,所以我們只需要按圖索驥,找出呼叫方,就可追蹤接收過程的完整流程。

追溯

容易看到FlutterJN.handlePlatformMessage呼叫了handleMessageFromDart,此函式被標記成@SuppressWarnings("unused"),很大可能與C++層有關了,搜尋方法名稱果然在``中找到"handlePlatformMessage", 函式簽名是"(Ljava/lang/String;[BI)V"正是些方法,方法物件被全域性變數g_handle_platform_message_method持有,又被FlutterViewHandlePlatformMessage引用, 至此又進入到C++層。

這裡HandlePlatformMessage這個名稱實在太讓人產生誤解,感覺像是C++層在處理平臺層發來的訊息,然而實際卻是傳遞Dart層的訊息到平臺,雖然handlePlatformXXX這種風格都表示處理Dart層的訊息,並且保持的很好,但還是沒有receiveXXX來的簡單直觀明瞭。

為便於理解以下是被呼叫序列

DartMessenger.handleMessageFromDart => PlatformMessageHandler
  FlutterJNI.handlePlatformMessage => g_handle_platform_message_method
    FlutterViewHandlePlatformMessage 
      PlatformViewAndroid::HandlePlatformMessage <= PlatformView::HandlePlatformMessage
       ...Shell::OnEngineHandlePlatformMessage <= PlatformView::Delegate::OnEngineHandlePlatformMessage
         Engine::HandlePlatformMessage <= RuntimeDelegate::HandlePlatformMessage
           RuntimeController::HandlePlatformMessage <= WindowClient::HandlePlatformMessage
             ::SendPlatformMessage
             ...tonic::DartCallStatic(::_SendPlatformMessage
             ...Window::RegisterNatives
複製程式碼

這與傳送端的序列層次完全一樣,從上到下分別是Shell -> PlatformView -> Engine -> RuntimeController -> Window。

可知FlutterViewHandlePlatformMessage是C++呼叫的終點,全域性變數g_handle_platform_message_method其實是平臺java方法,所以需要知道java方法何時與C++方法關聯起來的, 即g_handle_platform_message_method何時被設定的: 以下是被呼叫序列

g_handle_platform_message_method = env->GetMethodID(,"handlePlatformMessage",)
  ::RegisterApi
    PlatformViewAndroid::Register
      JNI_OnLoad
        System.loadLibrary("flutter") (library_loader.cc:23)
          FlutterMain.startInitialization (FlutterMain.java:161)
            FlutterApplication.onCreate (FlutterApplication.java:22)
複製程式碼

JNI_OnLoad被宣告在了連結器指令碼(android_exports.lst)中,表示被載入時執行的操作。

結語

結合前2篇的呼叫細節分析(精確到函式),及一些關鍵類的建立時機做一個簡明flutter通道資料通訊類圖如下: 左邊是java類,右邊是C++類

Flutter-Channel.jpg

相關文章