Flutter Platform Channel深度解析

一、簡介


Platform Channel 是 Flutter 端與 Platform 端制定的通信機制,由官方提供用於 Dart 和平臺之間的相互通信。


分爲以下 3 種

(1)BaseMessageChannel :用於傳遞字符串和半結構化的信息(在大內存數據塊傳遞的情況下使用)

(2)MethodChannel:用於傳遞方法調用(Method Invocation)

(3)EventChannel: 用於數據流(Event Streams)的通信


二、消息傳遞與編碼器


Flutter 的消息傳遞工具是 BinaryMessager ,通過它與 Platform 建立起通信關係,消息以二進制的格式進行傳遞。


dc5d306b795b9a717514783f7a90a758.png


如圖所示 BinaryMessager 的傳遞需要經過 BinaryMessageHandler,BinaryMessagerHandler 是以 Channel Name 作爲鍵值生成出來再被註冊到 BinaryMessager 上的,BinaryMessageHandler 和 BinaryMessager 是一一對應的,二進制格式的消息通過消息編碼器(Codec)解碼爲可識別的信息,並傳遞給 Handler 進行處理。Handler 處理完後,會把結果編碼爲二進制格式,再通過回調函數返回結果併發送回 Flutter 端。


1.編碼器分類


(1)MessageCodec:BinaryCodec、StringCodec、JSONMessageCodec、StandardMessageCodec

(2)MethodCodec:JSONMethodCodec、StandardMessageCodec


5386494ecf1a673dd15edcce15503484.png


經過消息編碼器處理後,消息就可以被 Handler 進行處理了。


2.消息編碼過程


Android 端的返回值是 java.lang.Integer 類型的,而 iOS 端返回值則是一個 NSNumber 類型的(通過 NSNumber numberWithInt:獲取)。而到了 Flutter 端時,這個返回值自動“變成 ”了 Dart 語言的 Int 類型。

standard platform channels 使用 standard messsage codec 對 message 和 response 進行序列化和反序列化,message與 response 可以是 booleans, numbers, Strings, byte buffers,List, Maps 等等,而序列化後得到的則是二進制格式的數據。


Flutter 默認的消息編碼器是 StandardMessageCodec ,支持的數據類型如下:



F3.png

三、MethodChannel


MethodChannel 是 Flutter 與 Platform 之間傳遞信息的一種,其傳遞過程是:BinaryMessager > BinaryMessagerHandler > MethodChannel。


e581b38a71d71ff5d9f3f0b0185c4799.png


如上圖:Native 端(iOS 和 Android)爲宿主端(host),Flutter 則是客戶端(client),Flutter 調用 Native 方法時,需要傳遞的信息是通過平臺通道傳遞到宿主端的,Native 收到調用的信息後方可執行指定的操作。如有返回的數據,則 Native 會將數據再通過平臺通道一併傳遞給 Flutter,其中數據傳遞是異步的,這樣就能確保消息傳遞時用戶界面不會被阻塞。


1.Flutter 層(Dart 層)


Flutter 端使用 MethodChannel 的 invokeMethod 方法發起一次方法調用時,開始了消息傳遞流程。invokeMethod 方法會將其入參 message 和 arguments 封裝成一個 MethodCall 對象,並使用 MethodCodec 將其編碼爲二進制格式數據,再通過 BinaryMessages 將消息發出。(注意,此處提到的類名與方法名均爲 Dart 層的實現)


上述過程最終會調用到 ui.Window 的 _sendPlatformMessage 方法,該方法是一個Native 方法,其實現在 Native 層,這與 Java 的 JNI 技術非常類似。我們向 Native 層發送了三個參數:

• name,String 類型,代表 Channel 名稱

• data,ByteData 類型,即之前封裝的二進制數據

• callback,Function 類型,用於結果回調


2.Native 層


到 Native 層後,window.cc 的 SendPlatformMessage 方法接受了來自 Dart 層的三個參數,並對它們做了一定的處理:Dart 層的回調 callback 封裝爲 Native 層的 PlatformMessageResponseDart 類型的 response;dart 層的二進制數據 data 轉化爲 std::vector<uint8t> 類型數據 data;根據 response, data 以及 Channel 名稱 name 創建一個 PlatformMessage 對象,並通過dartstate->window()->client()->HandlePlatformMessage 方法處理 PlatformMessage 對象。


dart_state->window()->client()是一個 WindowClient,而其具體的實現爲 RuntimeController,RuntimeController 會將消息交給其代理 RuntimeDelegate 處理。


RuntimeDelegate 的實現爲 Engine,Engine 在處理 Message 時,會判斷該消息是否是爲了獲取資源(channel 等於"flutter/assets"),如果是,則走獲取資源邏輯,否則調用 Engine::Delegate 的 OnEngineHandlePlatformMessage 方法。


Engine::Delegate 的具體實現爲 Shell,其 OnEngineHandlePlatformMessage 接收到消息後,會向 PlatformTaskRunner 添加一個 Task,該 Task 會調用 PlatformView 的 HandlePlatformMessage 方法。值得注意的是,Task 中的代碼執行在 Platform Task Runner 中,而之前的代碼均執行在 UI Task Runner 中。


四、消息處理


PlatformView 的 HandlePlatformMessage 方法在不同平臺有不同的實現,但是其基本原理是相同的。


88d495138178518104bb77218c8e9cb5.png


1.PlatformView


AndroidPlatformViewAndroid 是 Platformview 的子類,也是其在 Android 端的具體實現。當 PlatformViewAndroid 接收到 PlatformMessage 類型的消息時,如果消息中有 response(類型爲 PlatformMessageResponseDart),則生成一個自增長的 responseid,並以 responseid 爲key,response 爲 value 存入字典 pendingresponses 中。接着,將 channel 和 data 均轉化爲 Java 可識別的數據,通過 JNI 向 Java 層發起調用,將 response_id、channel 和 data 傳遞過去。


Java 層中,被調用的代碼爲 FlutterNativeView (BinaryMessager 的具體實現)的 handlePlatformMessage ,該方法會根據 channel 找到對應的 BinaryMessageHandler 並將消息傳遞給它處理。


BinaryMessageHandler 處理完成後,FlutterNativeView 會通過 JNI 調用 native 的方法,將 responsedata 和 responseid 傳遞到 native 層。


Native 層,PlatformViewAndroid 的 InvokePlatformMessageResponseCallback 接收到了 respondid 和 responsedata。其先將 responsedata 轉化爲二進制結果,並根據 responseid,從 pandingresponses 中找到對應的 PlatformMessageResponseDart 對象,調用其 Complete 方法將二進制結果返回。


2.PlatformViewIOS


PlatformViewIOS 是 PlatformView 的子類,也是其在 iOS 端的具體實現,當 PlatformViewIOS 接收到 message 時會交給 PlatformMessageRouter 處理。


PlatformMessageRouter通過 PlatformMessage 中的 channel 找到對應的 FlutterBinaryMessageHandler,並將二進制消息其處理,消息處理完成後,直接調用 PlatformMessage 對象中的 PlatformMessageResponseDart 對象的 Complete 方法將二進制結果返回。


3.結果回傳


PlatformMessageResponseDart 的 Complete 方法向 UI Task Runner 添加了一個新的 Task,這個 Task 的作用是將二進制結果從 native 的二進制數據類型轉化爲 Dart 的二進制數據類型 response,並調用 Dart 的 callback 將 response 傳遞到 Dart 層。


Dart 層接收到二進制數據後,使用 MethodCodec 將數據解碼,並返回給業務層。至此,一次從 Flutter 發起的方法調用就完整結束了。


五、具體使用


88301e6218156a4f9be6a81a0ad446f5.png


1.Flutter 端調用 Android 方法


2.Android 端代碼


(1)繼承 MethodCallHandler 並設置 Handler ,MethodChannel 需要保存在對象一會調用回調時需要使用,onMethodCall 爲 Flutter 層回調的方法這邊用 RCIMFlutterWrapper 承接處理。


db72968a6a663c7ff2443e602da5fd4f.png


(2)RCIMFlutterWrapper 類中處理, MethodCall 的 Method,對應 Flutter 層調用 invokeMethod 方法的傳入的第一個參數,兩端需完全對應一致。


spacer.gifF8.png

74623466ba75ade42664448af9198c94.png


(3)直接通過 result 對象回調回去,這樣就能將結果回調。


3.關於 Android 回調 Flutter 的使用


6e48682b7dc657ce12721485dcef8f7f.png


(1)Flutter 端回調監聽,設置監聽 Key 兩端對應。


0e48e8f25e554965e8b2b84e8b0bb9d7.png


(2)Android 端代碼回調,mChannel.invokeMethod 方法將數據回調給 Flutter 層。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章