由於今天老朋友來訪
只能偷偷拿舊文章補救一下
文章內容主要來自官網對於 Flutter Architecture 上的描述
後續再做修正與調整
那一樣開始今天的內容吧
大多數Widget的狀態是不會改變的,而這些會屬於StatelessWidget
然而如果有需要進行內容的變動時,則此時這個Widget就會是stateful
ex. 使用者點擊按鈕而改變Widget所表示的數值,此時則需要重建並更新UI
此時Widgets屬於StatefulWidget
為了傳遞 State
的方便這裡提出了 InheritedWidget
可成為共享資料的祖先
由上圖可知,此時 ExamListWidget
及 GradeWidget
可同時從 StudentState
取得資料
final studentState = StudentState.of(context);
of(content)將回傳距離當前widget最近的祖先節點
並且符合 StudentState
這個資料型別
可推論若單純只是要找上面的節點可透過 Widget.of(context)
來取得
而 Flutter 在 InheritedWidget
裡提供 updateShouldNotify()
方法
Flutter 將透過它去得知狀態更新時需呼叫哪個子節點的 Widget
透過 InheritedWidget 可達到節點下面Theme資料一致的功能
而目前相關的套件諸如
這個部分則仰賴 Skia
(由 C/C++ 所撰寫的圖形引擎,將呼叫 CPU 或 GPU 進行圖形繪製)
大多數跨平台框架會建立虛擬層在 Andriod 及 iOS 的UI繪製層上
後續再由直譯式語言如 JavaSript 來互動並繪製UI
而當使用者進行大量UI操作時,則可能會產生許多的負擔
而相對的 Flutter 繞過原先系統提供UI程式庫
而是透過自己 Widget Set 來進行繪製Dart
將其編譯成由 Skia
繪製的原生代碼
Flutter允許開發者升級他們的APP持續具備最新的效能增長
以上為Flutter的渲染流程
首先建置的過程中會先產生出 Widgets 樹
而觀察 Container
原始碼則會發現它會由很多的Widgets共同組成
因此在Debug工具中所看到的樹狀架構才會如此的深
然而 Widgets 樹在渲染前會被轉化成 Element Tree
其中便有以下兩種
雖然Widgets Objects會被重新建立出來
但在的渲染主要參照的部分則會透過Elements Tree
因此Flutter會透過Walk through Widgets Tree 確保有修改的部分進行重新建立即可
RenderObject
是所有 Render Tree 的基本類別,定義了抽象的Model用於 Layout 及 Painting
在 Build 階段 Flutter 會對每個 RenderObjectElement 創建一個繼承於 RenderObject
大多的 Flutter 元件透過繼承自 RenderBox 來進行渲染
而 RenderBox
會提供基本的box constraint model,用來建立渲染物件的最大最小長寬
Flutter 進行Layout時,會透過DFS尋訪Render Tree節點並且由上至下將size constraint傳遞下來
在渲染時,子節點必須符合父節點所給予的限制條件
而子節點會向父節點傳遞在限制下建立時所設定的size
在走訪完成後 每個物件便準備好透過paint()來進行繪製了
在需要根據限制大小進行畫面設計時,便可透過這個方式來設定
而所有的 RenderObject 的最上層Root為 RenderView
它則代表總體 Render Tree 的結果
當有新的畫面要被Render時,會呼叫 compositeFrame()
在呼叫後則會產生 SceneNuilder 去更新場景
當場景完成後 RenderView 會將完成的場景傳遞給dart:ui Window.render() 來控制GPU繪製
Flutter 的引擎為具備平台未知性的,用 stable ABI (Application Binary Interface)來提供 Platform Embedder
除了六個平台以外 也能寫客製化的Platform Embedder
如在 樹莓派(Raspberry Pi)
上的遠端介面
每個平台有各自的API及限制
IOS 及 MacOS中
Flutter 將如同 UIViewController 及 NSViewController 被載入到 embedder中
Platform Embedder 將創建 FlutterEngine 提供 Dart VM及相關 Flutter Rutime 及FlutterViewController
的服務,其中FlutterViewController
將連接到FlutterEnfine
透過傳遞 UIKit 或 Cocoa 輸入事件,並且透過 Metal 或是 OpenGL渲染
Android中
如果 Activity來載入到 embedder 中
透過FlutterView來控制,根據布局及 z-ordering requirements 來進行渲染
Windows中
Flutter host傳統的 Win32 app
並且內容是透過 ANGLE (將 OpenGL API 轉成 DirectX 11 的程式庫) 來進行渲染
目前也正在進行 UWP app model的 Windows embedder
將直接透過 DirectX 12 直接調用 GPU 來取代 ANGLE
Flutter 提供多項的互動機制
可以操作由Kotlin、Swift或是原生的C語言based的API
可將原生的控制引進Flutter App內或是鑲嵌Flutter到既有的應用程式
Mobile及Desktop App中
Flutter 允許呼叫客製化的程式透過 Platform Channel
這可以使得App能透過 Dart Code 能與 平台限定程式碼之間通訊
透過創建一個共同的通道
我們可以在平台限定及Dart程式碼中傳遞、獲得訊息
資料可以在Dart中進行序列化(Map -> 格式化後的結果)
再到平台上進行反序列化
(Data -> HashMap (Android) or Dictionary (Swift))
以下是通道建立的範例
Dart 提供一個直接的機制binding原生程式碼透過dart:ffi
Foreign function Interface 由於不需要透過資料序列化
可被視為是更快速的平台通道 (Platform channel)
除此之外
Dart 中具備方式去向 heap 要求記憶體空間並且可以靜態或動態連結程式庫
以下為使用 FFI 的範例
Rendering native controls in a Flutter app
如果想include既有的平台componets到Flutter App中是如何處理的?
Flutter 解決這項問題透過 platform view widgets(AndroidView or UiKitView)
這將使我們能夠鑲嵌在每個平台上執行的內容至Flutter App
這邊透過 AndroidView 舉例
它主要提供了以下功能
Flutter App將被 Android activity 或 iOS 的UIViewController所託管
Flutter 內容也能夠被鑲嵌進入既有的Android 或 iOS App 透過相同的鑲嵌API
Flutter 的模組被設計成可以輕鬆的進行鑲嵌
不僅僅可以透過 Gradle 或是 XCode 來建置也可透過compile的方式做成 Android Archive 或是 iOS Framework binary來使用並且無須要求每個開發者都安裝Flutter
(當要進行部門合作時可這樣運作)
Flutter 引擎需要花費一段時間進行載入
因此為了最小化UI的延遲,最好是在所有初始化序列最前面進行Flutter 引擎的初始化
不然至少在Flutter繪製第一個畫面時進行初始化
如此一來才不會降低使用者體驗在App運作中
更多關於 Flutter 是如何載入至既有的 Android 及 iOS app可以在以下連結查看
Load sequence, performance and memory topic
Flutter Web Support
由於Dart原先設計便考量到要轉譯成JavaScript
因此當 Flutter App 需要進行轉化成 JavaScript 時便相對直接了
然而由於 Flutter 引擎是由 C++ 寫成
而其原先被設計成操縱底下OS而非Web Browser
因此便有了不同的方式去達成 Web Support
在Web中,Flutter 提供一個在基本瀏覽器之上的引擎
目前我們有兩種選項去進行Flutter內容的渲染
在開發階段
Flutter web 透過 dartdevc 來支援熱重啟(並非熱重載)
dartdevc
為支援增量編譯的編譯器
而當準備好要推出Web產品時
dart2js則會派上用場
為高優化過的JavaScript編譯器
可將 Flutter程式碼轉成壓縮過後的原始檔案
並且可被佈署至任意的 Web Server
並且能過透過deferred imports來提供單一檔案或拆成多個檔案
deferred imports
也可視為 lazy loading 僅在dart2js使用
開發時透過Dart VM可能看不出效果
Further information
關於 Flutter 的更多細節可從 Inside Flutter
來了解相關的指南及該框架的設計哲學