Flutter是什么
Flutter 是谷歌的移動 UI 框架,可以快速在 iOS 和 Android 上構(gòu)建高質(zhì)量的原生用戶界面躲舌,同時也支持Mac丑婿、Windows、Linux没卸、Web羹奉、嵌入式等等。Flutter 可以與現(xiàn)有的代碼一起工作约计。
在全世界诀拭,F(xiàn)lutter 正在被越來越多的開發(fā)者和組織使用,并且 Flutter 是完全免費煤蚌、開源的耕挨。
Flutter如何運轉(zhuǎn)的
Flutter 是重寫了一整套包括底層渲染邏輯和上層開發(fā)語言的完整解決方案。
Flutter 是怎么完成組件渲染的
想要了解flutter組件渲染铺然,要先從圖像顯示的基本原理說起
- 在計算機系統(tǒng)中俗孝,圖像的顯示需要 CPU、GPU 和顯示器一起配合完成:CPU 負責圖像數(shù)據(jù)計算魄健,GPU 負責圖像數(shù)據(jù)渲染赋铝,而顯示器則負責最終圖像顯示。
- CPU 把計算好的沽瘦、需要顯示的內(nèi)容交給 GPU革骨,由 GPU 完成渲染后放入幀緩沖區(qū)农尖,隨后視頻控制器根據(jù)垂直同步信號(VSync)以每秒 60 次的速度,從幀緩沖區(qū)讀取幀數(shù)據(jù)交由顯示器完成圖像顯示良哲。
- 操作系統(tǒng)在呈現(xiàn)圖像時遵循了這種機制盛卡,而 Flutter 作為跨平臺開發(fā)框架也采用了這種底層方案。
flutter繪制原理如下圖
可以看出筑凫,F(xiàn)lutter 關(guān)注如何盡可能快地在兩個硬件時鐘的 VSync 信號之間計算并合成視圖數(shù)據(jù)滑沧,然后通過 Skia 交給 GPU 渲染:UI 線程使用 Dart 來構(gòu)建視圖結(jié)構(gòu)數(shù)據(jù),這些數(shù)據(jù)會在 GPU 線程進行圖層合成巍实,隨后交給 Skia 引擎加工成 GPU 數(shù)據(jù)滓技,而這些數(shù)據(jù)會通過 OpenGL 最終提供給 GPU 渲染。
Skia是什么棚潦?
可以看出令漂,Skia是Flutter的底層圖像渲染引擎,由它向 GPU 提供視圖數(shù)據(jù)丸边。那么這個Skia具體是什么呢
Skia 是一款用 C++ 開發(fā)的叠必、性能彪悍的 2D 圖像繪制引擎,其前身是一個向量繪圖軟件妹窖。2005 年被 Google 公司收購后纬朝,因為其出色的繪制表現(xiàn)被廣泛應(yīng)用在 Chrome 和 Android 等核心產(chǎn)品上。Skia 在圖形轉(zhuǎn)換骄呼、文字渲染玄组、位圖渲染方面都表現(xiàn)卓越,并提供了開發(fā)者友好的 API谒麦。
目前,Skia 已然是 Android 官方的圖像渲染引擎了哆致,因此 Flutter Android SDK 無需內(nèi)嵌 Skia 引擎就可以獲得天然的 Skia 支持绕德;而對于 iOS 平臺來說,由于 Skia 是跨平臺的摊阀,因此它作為 Flutter iOS 渲染引擎被嵌入到 Flutter 的 iOS SDK 中耻蛇,替代了 iOS 閉源的 Core Graphics/Core Animation/Core Text,這也正是 Flutter iOS SDK 打包的 App 包體積比 Android 要大一些的原因胞此。
底層渲染能力統(tǒng)一了臣咖,上層開發(fā)接口和功能體驗也就隨即統(tǒng)一了,開發(fā)者再也不用操心平臺相關(guān)的渲染特性了漱牵。也就是說夺蛇,Skia 保證了同一套代碼調(diào)用在 Android 和 iOS 平臺上的渲染效果是完全一致的。
Flutter為什么選用Dart酣胀?
Flutter 為什么選擇了 Dart刁赦,而不是前端應(yīng)用的準官方語言 JavaScript 呢娶聘?這個問題很有很有爭議
但,Google 公司給出的原因很簡單也很直接:Dart 語言開發(fā)組就在隔壁甚脉,對于 Flutter 需要的一些語言新特性丸升,能夠快速在語法層面落地實現(xiàn);而如果選擇了 JavaScript牺氨,就必須經(jīng)過各種委員會和瀏覽器提供商漫長的決議狡耻。
當然,Google 公司選擇使用 Dart 作為 Flutter 的開發(fā)語言猴凹,我想還有其他更有說服力的理由:
- Dart 同時支持即時編譯 JIT 和事前編譯 AOT夷狰。在開發(fā)期使用 JIT,開發(fā)周期異常短精堕,調(diào)試方式顛覆常規(guī)(支持有狀態(tài)的熱重載)孵淘;而發(fā)布期使用 AOT,本地代碼的執(zhí)行更高效歹篓,代碼性能和用戶體驗也更卓越瘫证。
- Dart 作為一門現(xiàn)代化語言,集百家之長庄撮,擁有其他優(yōu)秀編程語言的諸多特性(比如背捌,完善的包管理機制)。也正是這個原因洞斯,Dart 的學習成本并不高毡庆,很容易上手。
- Dart 避免了搶占式調(diào)度和共享內(nèi)存烙如,可以在沒有鎖的情況下進行對象分配和垃圾回收么抗,在性能方面表現(xiàn)相當不錯。
Flutter的實現(xiàn)原理
flutter的架構(gòu)圖如下
Flutter 架構(gòu)采用分層設(shè)計亚铁,從下到上分為三層蝇刀,依次為:Embedder、Engine徘溢、Framework吞琐。
- Embedder 是操作系統(tǒng)適配層,實現(xiàn)了渲染 Surface 設(shè)置然爆,線程設(shè)置站粟,以及平臺插件等平臺相關(guān)特性的適配。從這里我們可以看到曾雕,F(xiàn)lutter 平臺相關(guān)特性并不多奴烙,這就使得從框架層面保持跨端一致性的成本相對較低。
- Engine 層主要包含 Skia、Dart 和 Text缸沃,實現(xiàn)了 Flutter 的渲染引擎恰起、文字排版、事件處理和 Dart 運行時等功能趾牧。Skia 和Text 為上層接口提供了調(diào)用底層渲染和排版的能力检盼,Dart 則為 Flutter 提供了運行時調(diào)用 Dart 和渲染引擎的能力。而Engine 層的作用翘单,則是將它們組合起來吨枉,從它們生成的數(shù)據(jù)中實現(xiàn)視圖渲染。
- Framework 層則是一個用 Dart 實現(xiàn)的 UI SDK哄芜,包含了動畫貌亭、圖形繪制和手勢識別等功能。為了在繪制控件等固定樣式的圖形時提供更直觀认臊、更方便的接口圃庭,F(xiàn)lutter還基于這些基礎(chǔ)能力,根據(jù) Material 和 Cupertino 兩種視覺設(shè)計風格封裝了一套 UI 組件庫失晴。我們在開發(fā) Flutter的時候剧腻,可以直接使用這些組件庫。
Flutter的工作流程
頁面中的各界面元素(Widget)以樹的形式組織涂屁,即控件樹书在。Flutter 通過控件樹中的每個控件創(chuàng)建不同類型的渲染對象,組成渲染對象樹拆又。而渲染對象樹在 Flutter 的展示過程分為四個階段:布局儒旬、繪制、合成和渲染帖族。
- 布局:Flutter 采用深度優(yōu)先機制遍歷渲染對象樹栈源,決定渲染對象樹中各渲染對象在屏幕上的位置和尺寸。在布局過程中竖般,渲染對象樹中的每個渲染對象都會接收父對象的布局約束參數(shù)凉翻,決定自己的大小,然后父對象按照控件邏輯決定各個子對象的位置捻激,完成布局過程。為了防止因子節(jié)點發(fā)生變化而導致整個控件樹重新布局前计,F(xiàn)lutter 加入了一個機制——布局邊界(Relayout Boundary)胞谭,可以在某些節(jié)點自動或手動地設(shè)置布局邊界,當邊界內(nèi)的任何對象發(fā)生重新布局時男杈,不會影響邊界外的對象丈屹,反之亦然。
- 繪制:布局完成后耻卡,渲染對象樹中的每個節(jié)點都有了明確的尺寸和位置疫粥。Flutter 會把所有的渲染對象繪制到不同的圖層上。與布局過程一樣槽惫,繪制過程也是深度優(yōu)先遍歷先蒋,而且總是先繪制自身骇钦,再繪制子節(jié)點。為了解決性能損耗竞漾,F(xiàn)lutter 提出了與布局邊界對應(yīng)的機制——重繪邊界(Repaint Boundary)眯搭。在重繪邊界內(nèi),F(xiàn)lutter 會強制切換新的圖層业岁,這樣就可以避免邊界內(nèi)外的互相影響鳞仙,避免無關(guān)內(nèi)容置于同一圖層引起不必要的重繪。重繪邊界的一個典型場景是 Scrollview笔时。ScrollView 滾動的時候需要刷新視圖內(nèi)容棍好,從而觸發(fā)內(nèi)容重繪。而當滾動內(nèi)容重繪時允耿,一般情況下其他內(nèi)容是不需要重繪的借笙,這時候重繪邊界就派上用場了。
- 合成:終端設(shè)備的頁面越來越復雜右犹,因此 Flutter 的渲染樹層級通常很多提澎,直接交付給渲染引擎進行多圖層渲染,可能會出現(xiàn)大量渲染內(nèi)容的重復繪制念链,所以還需要先進行一次圖層合成盼忌,即將所有的圖層根據(jù)大小、層級掂墓、透明度等規(guī)則計算出最終的顯示效果谦纱,將相同的圖層歸類合并,簡化渲染樹君编,提高渲染效率
- 渲染:合并完成后跨嘉,F(xiàn)lutter 會將幾何圖層數(shù)據(jù)交由 Skia 引擎加工成二維圖像數(shù)據(jù),最終交由 GPU 進行渲染吃嘿,完成界面的展示祠乃。具體如上所述