使用Flutter之後,我們的CPU佔用率降了50%

近年來,移動互聯網迅猛發展,業務需求頻繁更新,業務內容動態化需求急劇增加,純原生開發已經無法滿足業務快速增長的需求,因此誕生了多種跨平臺開發框架,如 H5+ 原生開發、React Native 和 Weex ,但這兩年最受開發者青睞的莫過於 Flutter。目前,很多應用都集成了 Flutter,我們團隊也在漲樂財富通上實現了完整 Flutter 的集成過程,以下篇幅會具體介紹整個集成過程。

漲樂 Flutter 實踐(以 iOS 爲例)

此次實踐主要是爲了驗證整個流程,爲後續大規模應用 Flutter 做鋪墊,因此我們選擇了一個業務相對簡單的“技術論市”頁面進行改造,該頁面之前是H5實現的列表頁,點擊欄目會跳轉到另一個H5頁面詳情頁。

改造之後,原生界面點擊按鈕會打開 Flutter 列表頁,點擊 Flutter 頁面的欄目會跳轉到 H5 頁面,點擊返回可依次返回到上一個界面。從圖中可以看出,整個流程的使用體驗非常流暢。

組件化集成

如何將 Flutter 代碼集成進現有工程是我們遇到的第一個挑戰。Flutter 官網提供了一種解決方案,但存在以下缺陷:

1.需要修改主工程的配置,入侵原有工程;

2.工程運行需要 Flutter環境,而在實際開發中並不是所有的團隊成員都會參與到 Flutter 的開發,安裝 Flutter 環境對於那些不需要 Flutter 開發的成員來說顯然不合理。

官網的方案行不同,我們必須另闢蹊徑。研究 Flutter 的編譯腳本xcode_backend.sh發現,只要將 Flutter 編譯產物放入主工程就能運行 Flutter 模塊。爲了便於管理,漲樂財富通採用私有 pod 管理編譯產物的方式來集成 Flutter。

Flutter 工程的編譯產物包含三個部分,分別是:

1.App.framework:所有的 Dart 代碼,包括業務代碼和依賴的第三方 package 代碼,在 Debug 模式下只是一個空殼,在 Release 模式下是所有代碼生成的機器碼。

2.Flutter.framework:Flutter 的 SDK。

3.flutter_assets:Flutter 資源文件,包括字體、圖片等。

創建私有 pod 用來管理這些編譯產物,podspec 的核心內容如下:

  s.source_files = 'htflutter_product_debug/Plugin/**/*'

  s.vendored_frameworks = 'Framework/*.framework', 'Framework/engine/*.framework'
  s.resources = 'Framework/flutter_assets'

主工程需要集成 Flutter 模塊時,只需要在 podfile 中依賴該私有 pod 即可。

混合棧管理

引入 Flutter 模塊後,需要考慮的就是如何管理混合棧。在現有應用中,已經存在原生 + 網頁的混合棧,如今引入了 Flutter 需要解決這三者如何嵌套。
混合棧管理的方案必須具備以下特點:

1.原生、H5、Flutter 頁面三者能相互調用,並且用戶感覺不到差異;

2.儘量減少資源消耗;

3.每個頁面的生命週期保持完整。

爲此,我們借鑑了閒魚團隊開源的混合棧管理方案,並與我們現有的路由管理方案相結合,在漲樂上實現了混合棧管理,具體架構圖如下:

  • 頁面跳轉使用統一的路由管理。

漲樂財富通使用路由管理器來統一管理頁面。當需要打開一個 Flutter 頁面時,只需要像原來一樣,發送一個打開 Flutter 的路由,並攜帶參數用來標識具體的頁面。路由管理器識別到是 Flutter 路由後會創建新的WrapFlutterViewController並壓棧。WrapFlutterViewController會使用 FlutterViewController單例作爲其子VC,利用傳遞過來在參數在FlutterViewController內部打開具體的 Flutter 頁面。

  • 所有的 Flutter 頁面共用一個 Flutter 實例,iOS 使用 FlutterViewController,Android 使用 FlutterNativeView

共用一個 Flutter 實例,既可以使得 Flutter 頁面之間實現數據通信和共享,也可以減少額外的資源消耗。因爲每一個 Flutter 實例會啓動三個線程,分別是 UI 線程、GPU 線程和 IO 線程,只創建一個 Flutter 實例減少了資源的使用。

  • 每一個 Flutter 頁面對應一個原生頁面。

每次 push/pop 一個 Flutter 頁面,一方面會操作 Flutter 實例內部的導航棧,另一方面在外部會 push/pop 一個原生的頁面,這樣可以確保 Flutter 頁面和原生頁面的同步。

自動化

整個 Flutter 的開發過程分爲以下兩大步驟:

1.編寫dart和plugin代碼並生成 App.framework,Flutter_Asset 文件夾和 Flutter.framework;

2.將編譯產物集成到iOS主工程;

自動化需要解決幾個關鍵問題:

1.如何區分 debug 和 release 模式下的產物包

2.自動化的流程應該如何控制

針對第一個問題,我們的解決辦法是創建兩個repo,htflutter_product_debughtflutter_product_release,開發使用 debug 產物,生產使用 release 產物。

第二個問題,我們參考的是 CocoaPods 的 pod 發佈流程,將 Flutter 主工程作爲一個私有 repo 來看待,通過 tag 觸發腳本生成產物,再 push 到htflutter_product_debughtflutter_product_release。具體流程如下圖:

1.首先htcftflutter是我們的 Flutter 主工程,包含所有的 Dart 源代碼和 plugin 代碼。

2.通過 tag 名觸發腳本,編譯出兩種模式的產物,例如 tag:debug_1.0則編譯出 debug prudoct。

3.將產物推送到遠端產物 pod repo(這一步實際上類似pod repo push)。這一步相對複雜一點,

首先需要 clone 遠端的產物 pod 到當前的某個臨時文件夾,然後將 Flutter 主工程中編譯的產物拷貝到臨時文件夾中,其中包含 App.framework,flutter_assets 文件夾以及 Flutter.framework,另外還有 plugin 相關文件。前面三個都好辦,直接拷貝即可,plugin 比較麻煩,plugin 的代碼通過 package 的形式引入到工程中,並不在 Flutter 主工程,需要從.flutter-plugins文件中讀取到各個 plugin 到路徑,然後到對應到路徑進行拷貝。拷貝完成之後,再通過腳本完成git的相關操作即可,最後push完成,刪除臨時文件夾,這樣htcftflutter不感知整個腳本執行過程。

4.iOS 主工程集成 Flutter 產物 pod,默認情況下podfile中依賴htflutter_product_debug,主工程打 release tag 時,觸發腳本將依賴修改成htflutter_product_release,並執行pod update
相關腳本如下:

 tool = HTTool.new(mode) //debug/release
 tool.build_ios() #編譯產物
 tool.clone_flutter_product_repo() #clone product repo
 tool.copy_products()   #拷貝產物
 tool.copy_plugin_code() #拷貝plugin 原生代碼
 tool.updateSpecVersion() #更新版本
 tool.push_flutter_product_repo() #push to product repo
 tool.remove_product_repo()#delete product repo after push

降級策略

Flutter 還處於快速迭代發展的階段,正式上線可能存在不確定的風險,爲此我們設計了具體的降級方案,應對 Flutter 發生異常的情況。

1.應用啓動時,服務器會下發 Flutter 降級配置表,key 是需要降級的 Flutter 頁面路徑,value 是需要執行的降級路由操作;

2.路由管理器響應 Flutter 路由時,會首先判斷需要打開的 Flutter 頁面是否需要降級,若需要,則會執行配置表中的路由操作,降級到網頁;反之則正常跳轉到 Flutter 頁面。

實踐結果

1.安裝包大小

引入 Flutter 之前,漲樂財富通的安裝包爲94MB,引入之後大小爲100MB,發現增大了6MB,這其中主要是引入了 Flutter 的 SDK,增加的大小在可以接受的範圍。

2.FPS 和 GPU

從上圖可以看出,Flutter 的 FPS接近60,和原生效果基本一致,而 H5 的 FPS 在50左右,遠不如 Flutter 優秀。兩者的 GPU 使用率基本相同。

3.內存

內存表現方面,H5 頁面使用的內存要小於 Flutter。

4.CPU

從 CPU 的佔用率來看,Flutter 佔用的 CPU 要遠遠小於 H5 頁面。

總結

從我們的實踐結果來看,Flutter 在性能方面擁有絕對優秀的體驗,但 Flutter 的開發生態還不夠成熟,完全取代原生開發實現跨平臺爲時尚早,但對於一些追求一致性、高性能的界面可以嘗試採用 Flutter 實現。我們漲樂財富通開發團隊也會持續跟進 Flutter 的發展,將 Flutter 推廣應用到更多業務場景中。

更多內容,請關注前端之巔。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章