作者:閒魚技術——石磬
背景
隨著Flutter的發展,國內越來越多的App開始使用Flutter。為了降低風險,大部分App採用漸進式方式引入Flutter,在App裡選幾個頁面用Flutter來編寫,但都碰到了相同的問題,在原生頁面和Flutter頁面共存的情況下,如何管理路由? 官方沒有提供這樣的解決方案,而FlutterBoost就是為了解決這個問題而生。FlutterBoost從開源後受到了社群開發者的歡迎,已經有很多App使用了FlutterBoost,社群開發者也很活躍,提了很多Issue和PR。感謝開發者的一路支援和包容,無論是意見反饋還是吐槽,我們都會認真看,會持續關注Issue。
使命
FlutterBoost的使命是讓開發者非常簡單的在原生App中開發Flutter頁面。 FlutterBoost做為Flutter sdk上層的解決方案,有一定的侷限性,我們需要依賴sdk更多的開放能力。因此我們同時在做兩件事情:
•
推動Flutter官方開放更多的底層介面
我們參與Flutter 組織的 Multiple Flutters[1] 的討論。也多次發郵件給Flutter團隊反饋sdk的Bug和一些無法支援的應用場景。 很欣慰的是在Flutter 2.0 上看到混合開發的重大進展,Flutter2.0 提供了 FlutterEngineGroup,FlutterEngineGroup建立一個新Engine,記憶體只增加180k,這個給我們提供了很多想象空間。但FlutterEngineGroup最大的問題是多Engine之間不是isolate層面的記憶體共享。 從目前看FlutterBoost這種單Engine記憶體共享的方式還不能被完全取代。
•
FlutterBoost的升級
雖然開源社群很活躍,star很多,使用者也很多,但FlutterBoost離優秀的開源專案還很遠。
FlutterBoost的問題
梳理了一下問題:
•
穩定性,每次Flutter釋出一個stable版本,開發者會來問我,FlutterBoost針對新版本適配了沒有?他們準備升級新版本,需要FlutterBoost能適配最新版本。而我每次都要針對新版本拉2個新分支(Androidx 和Support分支),進行適配。 時間長了,會產生很多分支,這個給分支管理帶來很大的成本,比如在某個分支上修復的issue要同步到其他分支,一不小心就會遺漏同步。
•
社群的issue沒有收斂的趨勢。
•
設計過於複雜,概念太多。這讓一個新手看FlutterBoost的程式碼很吃力。
這些問題促使我們重新梳理設計,為了徹底解決這些頑固的問題,我們做一次大升級,我們把這次升級命名為FlutterBoost 3.0(上一次升級是2.0)
FlutterBoost3.0做了什麼
針對上面的問題,我們做了幾個事項
•不侵入引擎,相容Flutter的各種版本,Flutter sdk的升級不需要再升級FlutterBoost,極大降低升級成本。•不區分Androidx和Support分支。•簡化架構和介面,和FlutterBoost2.0比,程式碼減少了一半。•雙端統一,包括介面和設計上的統一。•支援開啟Flutter頁面,不再開啟容器場景。•頁面生命週期變化通知更方便業務使用。•解決了2.0中的遺留問題,例如,Fragment接入困難、頁面關閉後不能傳遞資料、dispose不執行,記憶體佔用過高等。
架構圖
FlutterBoost外掛分為平臺和Dart兩端,中間通過Message Channel連線。平臺側提供了Flutter引擎的配置和管理、Native容器的建立/銷燬、頁面可見性變化通知,以及Flutter頁面的開啟/關閉介面等。而Dart側除了提供類似原生Navigator的頁面導航介面的能力外,還負責Flutter頁面的路由管理
不入侵引擎
為了解決官方引擎複用引起的問題,FlutterBoost2.0拷貝了Flutter引擎Embedding層的一些程式碼進行改造,這使得後期的升級成本極高。而FlutterBoost3.0採用繼承的方式擴充套件FlutterActivity/FlutterFragment等元件的能力,並且通過在適當時機給Dart側傳送appIsResumed訊息解決引擎複用時生命週期事件錯亂導致的頁面卡死問題。FlutterBoost3.0 也相容最新的官方釋出的 Flutter 2.0。
不區分Androidx和Support分支
FlutterBoost2.0通過自己實現FlutterActivityAndFragmentDelegate.Host介面來擴充套件FlutterActivity和FlutterFragment的能力,而getLifecycle是必須實現的介面,這就導致對androidx的依賴。 這也是為什麼FlutterBoostView的實現沒有被放入FlutterBoost3.0外掛中的原因。而FlutterBoost3.0通過繼承的方式擴充套件FlutterActivity/FlutterFragment的能力的額外收益就是,可以做到不依賴androidx。
雙端設計統一,介面統一
很多Flutter開發者只會一端,只會Android 或者只會IOS,但他需要接入雙端,所以雙端統一能降低他的 學習成本和接入成本。FlutterBoost3.0,在設計上 Android和IOS都做了對齊,特別介面上做到了引數級的對齊。
支援 “開啟flutter頁面不再開啟容器” 場景。
在很多場景下,Flutter 頁面跳轉Flutter 頁面,這個時候可以不需要再開啟容器。不開啟容器,能節省記憶體開銷。 在FlutterBoost3.0上,開啟容器和不開啟容器的區別表現在使用者介面上僅僅是withContainer引數是否為true就好。程式碼如下:
InkWell(
child: Container(
color: Colors.yellow,
child: Text(
'開啟外部路由',
style: TextStyle(fontSize: 22.0, color: Colors.black),
)),
onTap: () => BoostNavigator.of().push("flutterPage",
arguments: <String, String>{'from': widget.uniqueId}),
),
InkWell(
child: Container(
color: Colors.yellow,
child: Text(
'開啟內部路由',
style: TextStyle(fontSize: 22.0, color: Colors.black),
)),
onTap: () => BoostNavigator.of().push("flutterPage",
withContainer: true,
arguments: <String, String>{'from': widget.uniqueId}),
)
複製程式碼
生命週期的精準通知
在FlutterBoost2.0上,每個頁面都會收到頁面生命週期通知,而FlutterBoost3.0只會通知頁面可見性實際發生了變化的頁面,介面也更符合flutter的設計。
Top Issue 解決
對於反饋比較多的issue進行了統計和歸類,主要解決了以下issue
•頁面關閉後引數的傳遞,之前只有iOS支援,android不支援,目前在dart側實現,Ios 和Android 都支援•解決了Android 狀態列字型和顏色問題。•解決了頁面回退willpopscope不起作用問題。•解決了不在棧頂的頁面也收到生命週期回撥的問題•解決了多次setState耗效能問題。•提供了Framgent 多種接入方式的Demo,方便tab 場景的接入。•生命週期的回撥程式碼,可以使用者程式碼裡面with的方式接入,使用更簡單。•全面簡化了,接入成本,包括 dart側,android側和ios•豐富了demo,包含了基本場景,方便使用者接入 和測試迴歸。
FlutterBoost3.0 接入和使用
接入方式
flutter_boost:
git:
url: 'https://github.com/alibaba/flutter_boost.git'
ref: 'v3.0-beta.3'
複製程式碼
目前FlutterBoost3.0 釋出了beta版本,目前屬於公測階段。
介面文件
對Flutter2.0 新特性 FlutterEngineGroup
FlutterBoost 是採用單Engine的方案,所以整個App是在同一個Isolate下,記憶體共享,而FlutterEngineGroup是採用多Engine方案,每個頁面是一個Engine,或者一個頁面內包含多個Engine,每個Engine對應一個Isolate,記憶體不共享。 從FlutterEngineGroup生成的FlutterEngine ,記憶體只增加180k。因為它對常用資源進行共享(例如 GPU 上下文、字型度量和隔離執行緒的快照),加快首次渲染的速度、降低延遲並降低記憶體佔用。
那是不是有了FlutterEngineGroup就不需要FlutterBoost了?從目前看FlutterBoost這種單Engine的方案,有一定的合理性,還不能完全被替代。
FlutterBoost的未來發展
後續會繼續做這3件事情:
•FlutterBoost3.0會繼續在單Engine方向完善和優化,讓他更穩定,支援更多場景。•持續和Flutter 官方溝通,包括能否支援FlutterEngineGroup在isolate層面的記憶體共享。•探索Flutter2.0 多engine方案下新的混合棧。
References
[1]
Multiple Flutters: docs.google.com/document/d/…