Flutter和原生之間的祕密

| 導語 全部的跨平臺方案,不論是最先的WebApp和HybridApp,仍是以前很是火熱的RN和Weex,都面臨着如何平衡跨平臺性和效率這一問題。Flutter做爲新一代的跨平臺解決方案,傳說中性能直逼原生,它爲什麼如此優秀呢?讓咱們以Flutter的通訊機制爲起點,一塊兒探索Flutter和原生之間的小祕密。注:因爲做者不太熟悉iOS開發,因此本文大部分使用的都是Android視角。java

1、跨平臺機制大不一樣

跨平臺解決方案由來已久,《聊聊移動端跨平臺開發的各類技術》的做者將其大體分爲了如下幾種流派:react

  • Web 流:也被稱爲 Hybrid 技術,它基於 Web 相關技術來實現界面及功能android

  • 代碼轉換流:將某個語言轉成 Objective-C、Java 或 C#,而後使用不一樣平臺下的官方工具來開發git

  • 編譯流:將某個語言編譯爲二進制文件,生成動態庫或打包成 apk/ipa/xap 文件github

  • 虛擬機流:經過將某個語言的虛擬機移植到不一樣平臺上來運行react-native

以往最先的Hybrid開發,主要依賴於WebView。可是WebView是一個很重的控件,很容易產生內存問題,並且複雜的UI在WebView上顯示的性能很差。react-native技術拋開了WebView,利用JavaScriptCore來作橋接,將js調用轉爲native調用,只犧牲了小部分性能獲取的跨平臺開發。數據結構

react-native原理圖

Flutter實現跨平臺採用了更爲完全的方案。它既沒有采用WebView也沒有采用JavaScriptCore,而是本身實現了一臺UI框架,而後直接系統更底層渲染系統上畫UI。因此它採用的開發語言不是JS,而是Dart。Dart語言有着適合Flutter的良好的特性,詳情能夠看FAQ.爲何Flutter選擇使用Dart語言?框架

Flutter原理圖

2、Flutter和native的通訊方式

Platform channels architecture

Flutter和native間的通訊,應該分爲 Flutter主動發送 和 native主動發送 兩種狀況,而Flutter的官方文檔卻僅僅介紹了Flutter主動發送的方式。對於 native主動發送的方式提供了一個plugin做爲例子。具體的使用方式能夠點開官網連接查看,在這就再也不贅述了,主要是探尋一下兩邊的代碼究竟是怎麼相互調用的。async

  1. MethodChannel:

MethodChannel

Flutter之間的消息傳遞,是經過 MethodChannel 來完成。咱們先看它的構造函數。能夠發現,須要一個 name和一個可選的 MethodCodec。 name是這個 MethodChannel的標識,在後面會用到。 MethodCodec是個編/解碼器,其決定了咱們能傳遞什麼類型的數據。 StandarMethodCodec有以下規則:函數

Dart名(rtx) Android iOS
null null nil (NSNull when nested)
bool java.lang.Boolean NSNumber numberWithBool:
int java.lang.Integer NSNumber
int if 32 bits not enough java.lang.Long
int if 64 bits not enough java.math.BigInteger
double java.lang.Double NSNumber numberWithDouble:
String java.lang.String NSString
Uint8List byte[] FlutterStandardTypedData
Int32List int[] FlutterStandardTypedData
Int64List long[] FlutterStandardTypedData
Float64List double[] FlutterStandardTypedData
List java.util.ArrayList NSArray
Map java.util.HashMap NSDictionary
  1. invokeMethod()

invokeMethod()

查看invokeMethod()方法, method爲 MethodCall的標識, arguments則天然是參數了,值得注意的是這裏的參數必需要遵照上面的規則(默認狀況下不能直接傳自定義類,可是咱們能夠將其轉爲Json以後再傳遞,也能夠去改造 MethodCode,以此進行復雜數據結構的傳遞)。 注:能夠看到,其是一個 async標記的方法,返回值爲Future。那麼咱們在接受這個方法的返回值的時候,就必需要使用 await進行修飾。要調用使用 await,必須在有 async標記的函數中運行。具體調用和使用的方式能夠看官網的例子。在這咱們先繼續深刻。

  1. BinaryMessages.send()

BinaryMessages.send()

查看send()方法能夠發現一個頗有意思的事情,若是 _mockHandlers取出來的值不爲空的話,則message會直接被對應handler處理,不會再發送。查看 setMockMessageHandler()的註釋,官方的解釋是,該方法會將Message攔截,能夠用於測試。

  1. _sendPlatformMessage()——window.sendPlatformMessage()

_sendPlatformMessage()

這裏調用了一個native方法,那麼咱們就須要去找這個native方法。

  1. native 遇到native方法,先去engine中找同名的文件試試看,果真在window.cc中,找到了這個方法。而後能夠找到對應的native方法。

window.sendPlatformMessage()

這段代碼比較長,咱們一點點來看。 首先看64行,能夠獲取到一個有用信息,這個套機制僅能在主線程(isolate)上運行。 而後看最關鍵的方法: dart_state->window()->client()->HandlePlatformMessage()

順着找下去,能夠在 WindowClient中找到 HandlePlatformMessage(),可是能夠發現,這是一個純虛函數。這裏使用了一個比較取巧的方式去找,直接去找都有哪一個類繼承了 WindowClient,能夠發現只有 RuntimeController是繼承了這個類的,去看看這個方法的實現。

那麼這個client是什麼呢?是一個 RuntimeDelegate …………………… 跳啊跳啊,終於在 PlatformViewAndroid 找到了實現(固然對應的iOS的也有一個,這裏由於我比較熟悉Android,就只把Android的拿出來看),中間的過程沒什麼養分就不進行詳述了。

OK,經歷了重重關卡,終於找到了jni的方法。那麼也就是說,只要找到 g_handle_platform_message_method 所指向的方法,就能走入Android的世界了。(能夠提早關注一下 pending_responses_,這個變量在後面會提到)

用簡單暴力點的方法,直接去找賦值語句,發現只有一處,那麼不用想,確定是它了。

而後再找這個類名,就能夠在Flutter的Android工程中找到這個方法了。

  1. Android

終於回到了JAVA的世界,仍是比較感動的。其實這段代碼核心就在 onMessage()直接看一看這個方法的實現。

果真是一個抽象函數,並且有三個實現。那麼咱們就不能亂猜了,再回頭看一下 handler這變量究竟是個什麼類型。從133行能夠看到 handler 是以channel的name爲key從一個map( mMessageHandlers)中取出來的,那這個值是在哪被設置的呢?線索彷彿到這就斷掉了。別急,咱們先來回憶一下,使用 MethodChannel的步驟。(下圖爲中文官網教程截圖)

好了重點我已經圈出來了,跳進去看看就明白了。

那就肯定了 handler是 IncomingMethodCallHandler的對象。直接去看它的 onMessage方法。

終於,咱們看到了熟悉的 onMethodCall方法。

  1. 消息回覆 方法是調用了,那下一步就該考慮數據怎麼傳回去了。還記得第6點一開始有個回調函數嗎?上面的幾個reply調用的就是這個回調函數。

再看看這個回調函數,分別是調用了兩個native層的函數。empty的那個就不用看了,知道非empty的怎麼傳天然也就知道它怎麼傳了。在 platform_view_android_jni.cc中,咱們能夠找到對應的函數。

message_response看起來就像是一個回調函數。它是從 pending_responses_中取出來的。還記得第4點中有一個回調函數嗎?它在 native層中被封裝,並置入了 pending_responses_中(具體能夠仔細看第5點的過程,中間有提到,在這就不重複貼圖了),那麼這裏的 message_response通過一些處理以後,最終仍是會回到那個回調函數,這裏的過程就不詳述了。

  1. 總結 好了,至此一個閉環也就造成了。能夠看到,總體的通信流程是一個V形。


《IVWEB 技術週刊》 震撼上線了,關注公衆號:IVWEB社區,每週定時推送優質文章。

相關文章
相關標籤/搜索