加载序列、性能和内存
显示 Flutter UI 涉及哪些步骤?
本页描述了显示 Flutter UI 所涉及的步骤分解。了解这些步骤后,您可以更好地做出明智的决策,例如何时预热 Flutter 引擎,哪些操作可以在哪个阶段进行,以及这些操作的延迟和内存成本。
加载 Flutter
#Android 和 iOS 应用程序(集成到现有应用程序的两个支持平台)、完整的 Flutter 应用程序以及添加应用程序模式在显示 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 代码的 Dart 内存和并发性。在 JIT 模式下,它还负责在运行时将 Dart 源代码编译为机器代码。
在 Android 和 iOS 上,每个应用程序会话存在一个 Dart 运行时。
首次构造 Android 上的 FlutterEngine 以及首次在 iOS 上运行 Dart 入口点 时,会进行一次性的 Dart VM 启动。
此时,您的 Dart 代码的 快照 也将从您的应用程序的文件加载到内存中。
这是一个通用过程,即使您直接使用 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 应用程序或您的库的小部件树也将被创建和构建。如果您需要防止在 Flutter 代码中执行某些功能,那么 AppLifecycleState.detached 枚举值表示 FlutterEngine 未附加到任何 UI 组件,例如 iOS 上的 FlutterViewController 或 Android 上的 FlutterActivity。
将 UI 附加到 Flutter 引擎
#标准的完整 Flutter 应用程序在应用程序启动后立即移动到达到此状态。
在添加应用程序场景中,当您通过调用 startActivity() 使用 Intent 构建的 FlutterActivity.withCachedEngine() 在 Android 上附加 FlutterEngine 到 UI 组件时,会发生这种情况。或者,通过在 iOS 上使用 initWithEngine: nibName: bundle: 初始化 FlutterViewController 来呈现。
如果启动了 Flutter UI 组件而没有预热 FlutterEngine,例如使用 Android 上的 FlutterActivity.createDefaultIntent() 或 iOS 上的 FlutterViewController initWithProject: nibName: bundle:,也是如此。在这种情况下,会隐式创建 FlutterEngine。
在幕后,两个平台的 UI 组件都为 FlutterEngine 提供渲染表面,例如 Android 上的 Surface 或 iOS 上的 CAEAGLLayer 或 CAMetalLayer。
此时,您的 Flutter 程序生成的每帧 Layer 树将被转换为 OpenGL(或 Vulkan 或 Metal)GPU 指令。