跳到主内容

加载顺序、性能与内存

显示 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 代码(如果适用))。

当您在 AndroidiOS 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 上的 CAEAGLLayerCAMetalLayer

此时,您的 Flutter 程序每一帧生成的 Layer 树都会转换为 OpenGL(或 Vulkan 或 Metal)GPU 指令。