Flutter技術調研報告-20190125
作者: Android團隊 - 余天然 楊繼宇
1.Flutter簡介
1.1.什麼是Flutter
Flutter是Google開發的一套全新的跨平臺、開源UI框架,支援iOS、Android系統開發,並且是未來新作業系統Fuchsia的預設開發套件。自從2017年5月釋出第一個版本以來,目前Flutter已經發布了近60個版本,並且在2018年12月初發布1.0穩定版。
在Flutter誕生之前,已經有許多跨平臺UI框架的方案,比如基於WebView的Cordova、AppCan等,還有使用HTML+JavaScript渲染成原生控制元件的React Native、Weex等。
Flutter與用於構建移動應用程式的其它大多數框架不同,因為Flutter既不使用WebView,也不使用作業系統的原生控制元件。Flutter使用Skia作為其2D渲染引擎。
注意:Android系統內建Skia,iOS系統未內建Skia,所以ios的包會比Android更大。
1.2.Flutter架構圖
- Flutter Framework:純 Dart實現的 SDK
- 底下兩層:底層UI庫,提供動畫、手勢及繪製能力
- Rendering層:構建UI樹,當UI樹有變化時,會計算出有變化的部分,然後更新UI樹,最終將UI樹繪製到螢幕上
- Widgets層:基礎元件庫,提供了 Material 和Cupertino兩種視覺風格的元件庫
- Flutter Engine:純 C++實現的 SDK
- Skia:渲染引擎
- Dart:Dart執行時
- Text:文字排版引擎
1.3.Flutter渲染機制
1.Flutter 佈局渲染的整體流程
在Flutter介面渲染過程分為三個階段:佈局、繪製、合成,佈局和繪製在Flutter框架中完成,合成則交由引擎負責。
新增合成圖層的理由:由於直接交付給 GPU 多圖層檢視資料是低效率的,可能會重複繪製,所以還需要進行一步圖層的合成,最後才交由引擎負責光柵化檢視
2.虛擬DOM技術
Widget樹:就是我們的UI元件樹,但這個只是一種描述資訊,渲染引擎是不認識的
RenderObject樹:這才是渲染引擎真的認識的,我們需要將 Widget 轉化為能用來渲染檢視的 Render Object
虛擬DOM解決了一個重要的矛盾:就是 DOM 操作的效能損耗與頻繁進行區域性 DOM 操作的矛盾
沒用虛擬DOM之前:DOM會在每一次元素更新到來之時渲染一次DOM
用了虛擬DOM之後:虛擬DOM會先彙總各個元素的更新情況,通過diff演算法計算出與原來 DOM 樹的差異,最後通過一次 DOM 更新解決
1.4.Flutter編譯機制
Flutter之所以採用Dart語言,其中很重要的一點就是因為Dart同時支援JIT和AOT兩種編譯方式
-
基於JIT的快速開發週期:Flutter在開發階段採用,採用JIT模式,這樣就避免了每次改動都要進行編譯,實現極大的節省了開發時間;
-
基於AOT的釋出包: Flutter在釋出時可以通過AOT生成高效的ARM程式碼以保證應用效能。而JavaScript則不具有這個能力。
- JIT,Just-in-time,動態(即時)編譯,邊執行邊編譯;
- AOT,Ahead Of Time,指執行前編譯;
1.5.Flutter專案結構
- android:android平臺相關程式碼
- ios:ios平臺相關程式碼
- lib:flutter相關程式碼,我們主要編寫的程式碼就在這個資料夾
- test:用於存放測試程式碼
- pubspec.yaml:配置檔案,一般存放一些第三方的依賴。主要是用Dart的pub包管理工具
1.6.目前已使用Flutter的團隊
- 美團
- 閒魚
- 騰訊NOW直播
- Github等國外大廠
2.本次調研的目標
2.1.打包成aar,整合到老Android專案
已完成,整合過程基本順利,除了一個assets裡面的icudtl.dat檔案,因為gradle指令碼 3.0以上的bug,需要自己手動複製到app的assets目錄下,其它的問題都不大。
2.2.整合grpc
已完成,Dart呼叫grpc請求的方式非常簡單,一行程式碼可以搞定,都不需要額外的封裝了
2.3.完成多Item佈局的列表,實現App首頁效果
已完成,實現過程中主要踩了兩個坑:
- 滾動元件裡面再巢狀滾動元件,需要指定高度,不然子元件就是無限高度,導致報錯
- 縱向滑動巢狀橫向滑動,需要做一下適配
其它的一些問題,主要還是API的熟悉度問題,寫多了佈局以後,問題都不大。
3.Flutter的優勢
- 跨平臺,同一套程式碼適用於Android和ios兩個平臺,可以節省開發資源、測試資源
- 原生效能,使用Skia作為其2D渲染引擎,既不使用WebView,也不使用作業系統的原生控制元件,這樣不僅可以保證在Android和iOS上UI的一致性,而且也可以避免對原生控制元件依賴而帶來的限制及高昂的維護成本
- 開發效率高,Flutter的熱過載可以快速地進行測試、構建UI、新增功能並更快地修復錯誤
- 從底層C++到高層Dart,可擴充套件性高
- 整體開發環境要求不高,輕量編輯器+模擬器即可完成開發,已支援IDE:Android Studio和VSCode
4.目前發現的問題
4.1.重要問題
- 其官方程式語言為Dart,是一門全新的語言。所以說,上手成本比較高,對於移動端開發人員,語言以及框架都是全新的,整個技術棧的積累也都得從頭開始
- 編譯後的包體積較大
- 第三方工具庫,目前還比較欠缺,需要自己造輪子
- 錯誤提示資訊不夠友好,難以定位到具體程式碼行
- 遇到問題的寂寞,目前應用的人群還較少,有時候遇到問題在社群裡面搜不到解決方案
4.2.一般問題
- CPU架構相容性問題,預設生成的庫檔案只支援armeabi-v7a,後期應該可以修改編譯配置解決此問題
- 多個Feature同時請求時,可能有的收不到回撥,這個可能是Dart的訊息機制有關,需要進一步研究,非必現
- WebView的支援很弱
- 音視訊的支援很弱
- 整體API像Android ,對iOS開發者上手可能不是非常友好
- 圖片資源的多倍率適配問題,必須提供一倍圖,會增大應用體積
- 如何在Flutter中實現懸停效果,需要調研
- 如何在Flutter中實現富文字效果,需要調研
- Flutter和Android/ios之間的通訊機制,需要調研(已有MethodChannel方案,尚未實現)
- Flutter的國際化支援,需要調研
- Fluter UI實現巢狀層次太多,可閱讀程度不高(很低 )
- 境外環境依賴(有國內映象),新建專案
dart package get
不穩定 - Flutter的設計圖示準,比如畫素值,和Android和ios的設計標準有區別
- 圖片和文字混排,實現比較麻煩
- ListView的檢視複用機制,需要調研,感覺View多了會有點卡頓
- 網路圖片的快取機制,需要調研,目前Image所以支援網路圖片,但是關於它的快取,還不清楚
5.Demo調研結果
- Dart語法上手難度:中等,Dart的語法和響應式程式設計理念和原生開發還是有一定差別,更偏向Web開發
- UI實現難度:低,在繪製複雜頁面方便,比原生更有優勢,自定義元件非常方便
- API豐富性:一般,目前成熟的第三方庫還比較少
- 效能:好
-
幀率:目前只繪製了首頁,FPS基本在50fps以上,幾乎達到了一般遊戲的標準
-
記憶體:佔用低,首頁記憶體佔用在60m左右,比Android原生低 Flutter繪製的首頁,佔用60m左右
Android原生繪製的首頁,內建記憶體佔用240m左右
- 安裝包體積:較大,僅僅繪製了一個首頁,安裝包就達到了15M。Android專案整合Flutter之前,apk體積是22M,整合Flutter之後,apk體積是32M,增加了10M。
總結:在UI方面用Flutter開發確實很有優勢,可以加快開發速度,但是涉及系統服務方面的地方,還需要進一步調研
6.Demo資訊
7.Demo用到的元件
在Flutter中,一切皆元件,這一點需要特別注意
- StatelessWidget-無狀態元件
- StatefulWidget-有狀態元件
- Image-圖片
- Icon-圖示
- Text-文字
- Container-容器元件,內建Padding、寬高、背景、邊框等細節操作
- Center-居中顯示Layout
- Column-縱向排列Layout
- Row-橫向排列Layout
- Wrap-橫向排列Layout,自動換行
- CustomScrollView-支援巢狀滾動子控制元件的滾動檢視
- SliverToBoxAdapter-包裝普通控制元件,適配CustomScrollView
- ListView-單一的List元件,不支援PullRefresh
- GideView-網格元件
- Divider-分割線元件