Flutter是什么Flutter 是谷歌的移動 UI 框架,,可以快速在 iOS 和 Android 上構建高質(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繪制原理如下圖 flutter繪制原理.png 可以看出,F(xiàn)lutter 關注如何盡可能快地在兩個硬件時鐘的 VSync 信號之間計算并合成視圖數(shù)據(jù),,然后通過 Skia 交給 GPU
渲染:UI 線程使用 Dart 來構建視圖結構數(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)被廣泛應用在 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ā)者再也不用操心平臺相關的渲染特性了,。也就是說,Skia 保證了同一套代碼調(diào)用在 Android 和 iOS 平臺上的渲染效果是完全一致的,。 Flutter為什么選用Dart,?Flutter 為什么選擇了 Dart,而不是前端應用的準官方語言 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的架構圖如下 flutter架構圖,,引自architectural-overview Flutter 架構采用分層設計,從下到上分為三層,,依次為:Embedder,、Engine、Framework,。 Embedder 是操作系統(tǒng)適配層,,實現(xiàn)了渲染 Surface 設置,線程設置,,以及平臺插件等平臺相關特性的適配,。從這里我們可以看到,F(xiàn)lutter 平臺相關特性并不多,,這就使得從框架層面保持跨端一致性的成本相對較低,。 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還基于這些基礎能力,根據(jù)
Material 和 Cupertino 兩種視覺設計風格封裝了一套 UI 組件庫,。我們在開發(fā) Flutter的時候,,可以直接使用這些組件庫。
Flutter的工作流程頁面中的各界面元素(Widget)以樹的形式組織,,即控件樹,。Flutter 通過控件樹中的每個控件創(chuàng)建不同類型的渲染對象,組成渲染對象樹,。而渲染對象樹在 Flutter 的展示過程分為四個階段:布局,、繪制、合成和渲染,。 布局:Flutter
采用深度優(yōu)先機制遍歷渲染對象樹,,決定渲染對象樹中各渲染對象在屏幕上的位置和尺寸。在布局過程中,,渲染對象樹中的每個渲染對象都會接收父對象的布局約束參數(shù),,決定自己的大小,然后父對象按照控件邏輯決定各個子對象的位置,,完成布局過程,。為了防止因子節(jié)點發(fā)生變化而導致整個控件樹重新布局,F(xiàn)lutter
加入了一個機制——布局邊界(Relayout
Boundary),,可以在某些節(jié)點自動或手動地設置布局邊界,,當邊界內(nèi)的任何對象發(fā)生重新布局時,不會影響邊界外的對象,,反之亦然,。 繪制:布局完成后,渲染對象樹中的每個節(jié)點都有了明確的尺寸和位置,。Flutter
會把所有的渲染對象繪制到不同的圖層上,。與布局過程一樣,繪制過程也是深度優(yōu)先遍歷,而且總是先繪制自身,,再繪制子節(jié)點,。為了解決性能損耗,F(xiàn)lutter
提出了與布局邊界對應的機制——重繪邊界(Repaint Boundary),。在重繪邊界內(nèi),,F(xiàn)lutter
會強制切換新的圖層,這樣就可以避免邊界內(nèi)外的互相影響,,避免無關內(nèi)容置于同一圖層引起不必要的重繪,。重繪邊界的一個典型場景是
Scrollview。ScrollView
滾動的時候需要刷新視圖內(nèi)容,,從而觸發(fā)內(nèi)容重繪,。而當滾動內(nèi)容重繪時,一般情況下其他內(nèi)容是不需要重繪的,,這時候重繪邊界就派上用場了,。 合成:終端設備的頁面越來越復雜,因此 Flutter
的渲染樹層級通常很多,,直接交付給渲染引擎進行多圖層渲染,,可能會出現(xiàn)大量渲染內(nèi)容的重復繪制,所以還需要先進行一次圖層合成,,即將所有的圖層根據(jù)大小,、層級、透明度等規(guī)則計算出最終的顯示效果,,將相同的圖層歸類合并,,簡化渲染樹,提高渲染效率 渲染:合并完成后,,F(xiàn)lutter 會將幾何圖層數(shù)據(jù)交由 Skia 引擎加工成二維圖像數(shù)據(jù),,最終交由 GPU 進行渲染,完成界面的展示,。
|