本文將以 Android 視角,來扒一扒 Flutter 混合棧的前世今生。其實也就是從 1.0 正式釋出到現在 1.9 版本的一些變更。
本文將會從以下幾個方面來分析:
什麼是 Flutter 混合棧為什麼會產生問題處理混合棧的相關框架官方的處理方案一、什麼是混合棧一個新的技術的興起,必然是一步一步向前的,Flutter 在成熟的 Android、iOS 的大環境下的生存,必要與 native 融合。
一些成熟的 APP ,如果想使用 Flutter 技術,必然不會完全使用 Flutter 重寫,那樣的成本太高,所以 Native + Flutter 的專案就出現了,Native 頁面與 Flutter 頁面共存,甚至交替呈現在使用者手機上。
那什麼是混合棧呢?
相信你已經有了答案,下面我們用 Android 的視角來重新審視一下混合棧。
我們使用 flutter boost 框架提供的 demo 來看一下混合棧的效果(debug包)
二、為什麼會產生問題知道了混合棧問題,接下來我們要考慮為什麼會出現這樣的問題。
2.1.目標是什麼
現狀是一個 Activity 中存在多個 Flutter Page,我們想要的是 Flutter Page 與 Android Activity 可以一一對應,這樣便可以簡單的將兩個頁面棧合併成一個棧,並且在效能上不會產生影響,這就是我們處理混合棧的目標。
如上圖混合棧所示,Android 中以 FlutterView 承載 Flutter 的展示,預設情況下不同 FlutterView 建立了不同的 engine。如果一個 Flutter Page 對應一個 Activity, 這就導致了資源的多次重複建立和記憶體的不共享。
如果極端情況下,Native => Flutter => Native => … => Native => Flutter 會是什麼情況呢?後果不堪設想,當然,可以從業務上避免這樣的問題,但是作為框架的制定者,必須要考慮到這樣的問題。
接下來我們看如何解決問題。需要從原理入手,需要閱讀原始碼
2.2.Flutter 架構圖
從最經典的 Flutter 架構圖入手
從圖中可以看到 3 層架構,每層提供了不同的能力
Framework:這一層提供了Flutter 的常用控制元件,也提供了用於繪製的一些準備工作,Engine:這一層提供了Flutter的2D圖形渲染庫Skia和用於垃圾收集的面嚮物件語言的 Dart VM,並將它們託管在Shell中。這裡也提供了 Platform Channels 等與 Native 互動的 API。Embedder:這一層提供了不同平臺的嵌入 API 如 Andorid、iOS。使得 Flutter 可以執行在不同的嵌入式平臺。2.3.在 Android 中的 Flutter
我們看一下建立 Flutter 專案中自動生成的 Android 工程,內部使用的是 io.flutter.app 包內的 FlutterActivity,暫且不討論 io.flutter.embedding.android 包相關內容,後面會分析。
在 Android 中使用 Flutter 是這樣的
如上圖所示,圖中羅列了一些類,這裡講解一下
FlutterView:Android 中用於展示 Flutter 頁面的控制元件,一個 FlutterView 中可以展示多個 Flutter Widget,官方的註釋是:"An Android View containing a Flutter app"。內部包含了 FlutterNativeView。FlutterNativeView:每個 FlutterView 中包含一個FlutterNativeView,該類的主要作用是 Android 與 Flutter 之間的通訊,保持生命週期與 Activity 及 FlutterView 同步。內部包含了 DartExecutor。DartExecutor:根據名稱我們可以了解,這個類就是 Dart VM 相關處理 Java 與 C/C++ 的呼叫。官方的註釋是:"Configures, bootstraps, and starts executing Dart code"。其實 Flutter 的執行機制就是這樣的,Flutter 由 FlutterView 呈現。每一個 FlutterView,會對應的建立一個 FlutterNativeView,建立一個 Dart VM。而不同 FlutterView 內部的 Dart 程式碼記憶體無法共享。
2.4.原始碼閱讀
建議讀者閱讀一下程式碼
2.5.我們能做什麼
通過上面的介紹,應該依然了解 Flutter 在 Android 上的執行機制,如果閱讀了原始碼應該有更深的印象。在這樣的執行機制中,我們能做什麼呢?其實 Flutter Boost 框架給了我們解決的思路,但是這裡我還是希望讀者能自己來想想,如果是你自己來實現,該怎麼做呢?
三、混合棧處理框架來看看社群為我們提供的方案吧。
網上的文章很多,在文章最後提供一些連結,有興趣的讀者可以都看一下。這裡僅以 Flutter Boost 為例,來分析一下。
Flutter Boost 的處理方案可以分成兩個版本,使用了兩種方案,可以作為混合棧方案的兩種代表思路。
3.1.Flutter Boost 0.0.4+版本
3.2.FlutterView 複用方案
框架中從 FlutterActivityDelegate#onCreate 方法入手,重寫建立 FlutterView 的流程,複用 FlutterView 來實現。
我們先來看一下這個版本的接入方式,在 Application 中初始化
我們來看一下 FlutterActivityDelegate#onCreate 是如何處理的。
createFlutterView 的實現是在 FlutterActivity 中的。
而 Flutter Boost 框架重寫了 createFlutterView 方法
真正返回的是這裡構造的
這樣就複用了 FlutterView。
複用 FlutterView 需要在 Activity 切換的時候進行 view 的 attach、detach,該版本使用了截圖方案。
3.3.Flutter Boost 0.1.5+版本
FlutterEngine 複用
從接入方式來看,在 Application 中初始化,提供了一個回撥方法,提供 BoostFlutterEngine 即是 FlutterEngine 例項。
在看 BoostFlutterActivity 實現
真正返回的是這裡構造的
該版本的處理方式與 io.flutter.embedding 包中處理方式基本相同,使用了 flutter.jar 中的 FlutterSurfaceView 和 FlutterTextureView 來最終的展示 Flutter 介面。接下來我們看看 Flutter 官方為我們提供的方式。
官方提供的方式
通過文件我們就可以知道,該方式和 Flutter 專案自動生成的 Android 工程不同,使用的大多為 io.flutter.embedding 包中的內容,並且提供了使用快取的 FlutterEngine 的方式。使用了 FlutterEngineCache 類進行對 FlutterEngine 的 key-value 快取。
在 flutter.jar 中可以看到,共存了兩個 FlutterActivity、FlutterView 等。
FlutterActivity
FlutterView
這裡簡單介紹一下
載入到 Activity 上的 View 是如何建立的
看一下 FlutterView 是如何實現的
大致的流程就是這樣的。
最後本文如有錯誤或不當之處,歡迎讀者留言斧正,互相交流學習,小編不勝感激~如果你看到了這裡,覺得文章寫得不錯就給個讚唄!歡迎大家評論討論!定期免費分享技術乾貨。感興趣的小夥伴可以點一下關注哦。謝謝!最後我準備了一些面試的知識彙總,資料結構,計算機網路等等都有。自己整理和分類的,還請尊重知識產出。