首頁>技術>

本文將以 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 是如何實現的

大致的流程就是這樣的。

最後

本文如有錯誤或不當之處,歡迎讀者留言斧正,互相交流學習,小編不勝感激~如果你看到了這裡,覺得文章寫得不錯就給個讚唄!歡迎大家評論討論!定期免費分享技術乾貨。感興趣的小夥伴可以點一下關注哦。謝謝!最後我準備了一些面試的知識彙總,資料結構,計算機網路等等都有。自己整理和分類的,還請尊重知識產出。

  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • Appium 自動化測試