載入順序、效能與記憶體
顯示 Flutter UI 時涉及的步驟。
本頁面介紹了顯示 Flutter UI 所涉及的步驟分解。瞭解這些步驟後,您可以針對何時預熱 Flutter 引擎做出更明智的決策,瞭解哪些操作在哪個階段是可行的,以及這些操作的延遲和記憶體開銷。
載入 Flutter
#Android 和 iOS 應用(整合到現有應用中支援的兩個平臺)、完整的 Flutter 應用以及“新增到應用”(add-to-app)模式,在顯示 Flutter UI 時都具有相似的概念性載入步驟。
查詢 Flutter 資源
#Flutter 的引擎執行時和您應用的編譯後 Dart 程式碼在 Android 和 iOS 上都作為共享庫打包。載入 Flutter 的第一步是在您的 .apk/.ipa/.app 中查詢這些資源(以及其他 Flutter 資源,如圖片、字型和 JIT 程式碼(如果適用))。
當您在 Android 和 iOS API 上首次構建 FlutterEngine 時,就會發生這種情況。
載入 Flutter 庫
#找到後,引擎的共享庫會按程序載入一次到記憶體中。
在 Android 上,這也發生在構建 FlutterEngine 時,因為 JNI 聯結器需要引用 Flutter C++ 庫。在 iOS 上,這發生在首次執行 FlutterEngine 時,例如透過執行 runWithEntrypoint:。
啟動 Dart VM
#Dart 執行時負責管理 Dart 程式碼的記憶體和併發性。在 JIT 模式下,它還負責在執行時將 Dart 原始碼編譯為機器碼。
在 Android 和 iOS 的每個應用會話中,僅存在一個 Dart 執行時。
Dart VM 的啟動操作在 Android 上首次構建 FlutterEngine 時完成,在 iOS 上首次執行 Dart 入口點時完成。
此時,您 Dart 程式碼的 快照(snapshot)也會從應用檔案中載入到記憶體中。
這是一個通用過程,如果您直接使用 Dart SDK 而不使用 Flutter 引擎,也會發生此過程。
Dart VM 一旦啟動,就不會關閉。
建立並執行 Dart Isolate
#Dart 執行時初始化後,下一步是 Flutter 引擎對 Dart 執行時進行使用。
這是透過在 Dart 執行時中啟動一個 Dart Isolate 來完成的。Isolate 是 Dart 的記憶體和執行緒容器。此時,宿主平臺上的多個輔助執行緒也會被建立以支援該 Isolate,例如用於分擔 GPU 處理的執行緒和用於影像解碼的執行緒。
每個 FlutterEngine 例項存在一個 Isolate,同一個 Dart VM 可以託管多個 Isolate。
在 Android 上,當您在 FlutterEngine 例項上呼叫 DartExecutor.executeDartEntrypoint() 時會發生這種情況。
在 iOS 上,當您在 FlutterEngine 上呼叫 runWithEntrypoint: 時會發生這種情況。
此時,您 Dart 程式碼中所選的入口點(預設是 Dart 庫中 main.dart 檔案的 main() 函式)將被執行。如果您在 main() 函式中呼叫了 Flutter 的 runApp() 函式,那麼您的 Flutter 應用或庫的 widget 樹也會被建立並構建。如果您需要在 Flutter 程式碼中阻止某些功能的執行,AppLifecycleState.detached 列舉值表示 FlutterEngine 未連線到任何 UI 元件,例如 iOS 上的 FlutterViewController 或 Android 上的 FlutterActivity。
將 UI 附加到 Flutter 引擎
#標準的完整 Flutter 應用在應用啟動時就會進入此狀態。
在“新增到應用”場景中,當您將 FlutterEngine 附加到 UI 元件時會發生這種情況,例如在 Android 上使用透過 FlutterActivity.withCachedEngine() 構建的 Intent 呼叫 startActivity()。或者在 iOS 上展示透過 initWithEngine: nibName: bundle: 初始化的 FlutterViewController。
如果您未預熱 FlutterEngine 而直接啟動 Flutter UI 元件,也會出現這種情況,例如在 Android 上使用 FlutterActivity.createDefaultIntent(),或者在 iOS 上使用 FlutterViewController initWithProject: nibName: bundle:。在這些情況下,系統會自動隱式建立一個 FlutterEngine。
在後臺,兩個平臺的 UI 元件都會為 FlutterEngine 提供一個渲染表面,例如 Android 上的 Surface,或 iOS 上的 CAEAGLLayer 或 CAMetalLayer。
此時,您的 Flutter 程式每一幀生成的 Layer 樹都會轉換為 OpenGL(或 Vulkan 或 Metal)GPU 指令。