作者:閒魚技術-凱航
Flutter是一個使用Dart語言開發的跨平臺移動UI框架,通過自建繪製引擎,能高效能、高保真地進行Android和IOS開發。在業界還未出現過Base Flutter的大型商業應用實戰驗證的情況下,閒魚技術團隊在最複雜且重要的商品詳情頁作了相關的技術實踐並取得良好的結果。現嘗試通過本文向有興趣進行類似實踐的開發者或團隊分享過程中的思考/實踐過程。
Flutter特色
面對一系列移動開發技術:IOS、Android、Weex,RN, Kotlin,H5... Flutter究竟特色何在?

開發語言選擇
瞭解過Flutter的都知道,它採用Dart語言進行開發,而並非Java,Javascript這類熱門語言,這是Flutter團隊對當前熱門的10多種語言慎重評估後的選擇。因為Dart囊括了多數程式語言的優點,它更符合Flutter構建介面的方式。

Flutter vs ReactNative框架對比
ReactNative | Flutter |
---|---|
![]() |
![]() |
ReactNative
- 採用Javascript開發,需學React,成本高
- 需要JavaScript橋接器,實現JS到Native轉化,效能耗損
- 訪問原生UI,頻繁操作易出效能問題
- 支援線上動態性,可有效避免頻繁更新版本
Flutter
- 採用Dart開發,可直接編譯成Native程式碼(易學)
- 自帶UI元件和渲染器,僅依賴系統提供的Canvas(無橋接耗損)
- 暫不支援線上動態性
Flutter更多特色可以連結為什麼說Flutter是革命性的?
每個框架都是為解決特定問題而產生的,不存在最好的框架,只有最適合你團隊的框架。閒魚是個業務快速發展的App,為更多業務嘗試和探索,它採用現有流行的框架,能支援線上動態化需求。但出於個性化互動以及流暢性體驗(首頁、商品詳情、釋出閒置等),主鏈路依舊只採用原生開發。為兼顧跨端開發及高效能需求,閒魚經過充分呼叫,最終選擇了Flutter。為驗證Flutter的效能,閒魚挑選重要且複雜的主鏈路業務(商品詳情)作為首個Flutter頁面實踐點,以這種方式來快速暴露並解決Flutter相關問題。
閒魚Flutter突破點
Flutter與Native混合程式設計方案
隨著Flutter版本的不斷迭代,穩定性和質量逐漸完善,市場上純Flutter開發的App也不斷湧現。閒魚對Flutter採取“由點到面,逐一替換” 的策略,先將商品詳情遷移到Flutter頁面,後續逐步擴充套件到其他功能模組,但這樣就不可避免涉及到Flutter與Native頁面混合呼叫的場景(如下圖):

Flutter | Native(Android) |
---|---|
![]() |
![]() |
因此要混合呼叫就會涉及兩個問題:
- 混合棧管理
- 元件間呼叫
混合棧管理
Flutter出現的目的旨在統一Android/IOS兩端程式設計,因此完全基於Flutter開發的App,只需提供一個包含FlutterView的頁面,後續頁面增加/刪除/跳轉均在FlutterView的Navigator中進行管理。但現在閒魚只是將部分模組修改成Flutter開發,我們不可能為統一頁面棧管理而將其他所有頁面用Flutter重做一次,權衡成本與風險,亟需統一管理Native頁面和Flutter頁面跳轉互動的混合棧。為此,閒魚提出了4種解決方案(如下圖):

- 每啟動一個Activity就啟動一個新的FlutterView(方案4);
- 抽取單一FlutterView或FlutterNativeView,後續每啟動一個Activity都對FlutterView或FlutterNativeView進行復用(方案2或方案3);
考慮到每啟動一個頁面都新建立一套新的Flutter渲染機制,開銷過重,目前閒魚Flutter實踐採用方案2,相比而言,該方案效能相對穩定且易操作,下面就是否複用FlutterView進行對比,主要觀測Java記憶體和Native記憶體增加情況:
![[閒魚技術] Release Flutter的最後一公里](https://i.iter01.com/images/e0313756979176d4479e53cbf0ec2ed33db4c0fbea3623f16e2e5520b77508ae.png)
元件間呼叫

解決了Flutter與Native混合程式設計所面臨的問題後,接下來要處理的就是混編工程問題,出現該問題的原因還是我們的專案不是完全的Flutter工程(即:android /ios + Flutter)所致。混合工程專案結構以及Flutter產物如下圖:
專案結構

Flutter產物

其實對一般Flutter工程而言,採用AndroidStudio編譯Flutter與編譯Native工程方式一樣,當將其部署到server端採用mtl編譯時,server缺少Flutter編譯環境,因而導致Flutter工程無法編譯。解決此問題可以採取兩種方式:
- 在每個server端部署Flutter編譯環境
- Native工程遠端依賴Flutter編譯產物
對1,對各server端都去部署Flutter環境有點不切實際(若server就那麼幾臺也可以);對2,閒魚的做法是將Flutter工程編譯出的中間產物以AAR形式匯出並上傳至maven庫,最後Native工程以依賴包形式將AAR打入最終apk中,這樣處理後解耦了Native團隊對Flutter團隊的依賴。當然,具體實踐過程中肯定沒有這麼簡單,我們在編譯過程中對Pod/Gradle編譯指令碼、engine以及flutter_tools等均有所優化,對後續集團推廣Flutter奠定了基礎。
阿里Flutter生態適配
將Flutter應用於閒魚,不可避免需要使用集團提供的基礎元件庫,但這些元件庫都是Native,考慮到為後續Flutter在集團推廣,打造阿里Flutter生態圈,閒魚團隊對集團內部基礎元件庫做了適配支撐,後續可建立私有倉庫,直接Git引用。
生態適配原理及效能

多媒體解決方案
在以內容為王的時代,多媒體技術備受關注,效能的好壞直接影響使用者體驗,但Flutter多媒體預設功能存在以下缺陷:
- 功能單一,如:播放器缺少濾鏡,與Native淘寶播放器存在一定差距
- 相容性欠佳
為改善體驗,優化效能,閒魚對Flutter播放器以及圖片效能作出如下改進:
Texture對接自定義視訊播放器

具體方案:

圖片效能優化
有過移動開發經驗的都知道,圖片展示是OOM出現的高頻場景,而Flutter預設採用基於LRU演算法的圖片快取策略,且圖片快取MaxSize=1000,佔用記憶體較高,為此閒魚採用以下兩種策略對圖片效能進行優化

Flutter 上線效果 & 效能對比 & 成熟度
解決了Flutter存在的問題,要的就是產品能夠以一種效能穩定、互動流暢、介面美觀的姿態呈現在使用者面前,下面就以閒魚寶貝詳情線上Flutter版本為引,對Flutter應用頁面展示、效能以及成熟度進行闡述。
閒魚寶貝詳情Flutter應用線上效果
Native效能對比
測試環境
- 測試機型:iphone6
- IOS版本:11.3
- 閒魚版本: 6.1.3
- 測試方法: 在Flutter版本和Native版本各自寶貝詳情頁面執行相同操作:即從我釋出的頁面進行10個不同詳情頁面
注: 下圖僅對Flutter和Native效能進行了粗略對比

Flutter成熟度

延展討論
目前Flutter尚處於Preview階段,沒有經過大規模實踐驗證,框架成熟度及穩定性仍有待完善。上文僅僅是將閒魚團隊在實踐Flutter開發時碰到部分問題及解決方案進行了簡略闡述,一個產品從開發到上線所面臨的問題,肯定遠不及這些。隨著Flutter覆蓋場景的增加,難題也會不斷湧現,健全有效的效能及穩定性監控體系不可或缺。為建設基於Flutter全新的一體化研發體系,提高開發效率,對動態化需求、規範Dart編碼、統一中介軟體橋接機制、快速發版能力及完備的自動化測試建設等一系列問題亟需解決,倘若您對此感興趣,歡迎一起交流學習~
簡歷投遞:guicai.gyx@alibaba-inc.com