# 控制加载顺序，优化性能与内存

> 介绍在显示一个 Flutter 界面时有哪些步骤。



This page describes the breakdown of the steps involved
to show a Flutter UI. Knowing this, you can make better,
more informed decisions about when to pre-warm the Flutter engine,
which operations are possible at which stage,
and the latency and memory costs of those operations.

本页面描述了展示一个 Flutter UI 的分解步骤。
知道了这一点，你可以就何时对 Flutter 引擎进行预热，
在哪个阶段可以进行哪些操作，
以及这些操作的潜在问题和内存成本做出更好、更明智的决策。

## Loading Flutter

## 加载 Flutter

Android and iOS apps (the two supported platforms for
integrating into existing apps), full Flutter apps,
and add-to-app patterns have a similar sequence of
conceptual loading steps when displaying the Flutter UI.

在展示 Flutter UI 时，
Android 与 iOS 应用（用于集成到现有应用的两个受支持的平台），
纯 Flutter 应用，以及 add-to-app 的模式，在概念上的加载步骤顺序相似。

### Finding the Flutter resources

### 查找 Flutter 资源

Flutter's engine runtime and your application's compiled
Dart code are both bundled as shared libraries on Android
and iOS. The first step of loading Flutter is to find those
resources in your .apk/.ipa/.app (along with other Flutter
assets such as images, fonts, and JIT code, if applicable).

Flutter 的引擎运行时和应用已编译的 Dart 代码都被打包为 Android 和 iOS 上的共享库。
加载 Flutter 的第一步是在 .apk、.ipa 或 .app 中查找这些资源
（以及其他 Flutter 资源，例如图像和字体，假如适用的话还有 JIT 代码）。

This happens when you construct a `FlutterEngine` for the
first time on both **[Android][android-engine]**
and **[iOS][ios-engine]** APIs.

当你首次在 **[Android][android-engine]** 和 **[iOS][ios-engine]** 
上调用 API 构建 `FlutterEngine` 时，就会发生这种情况。

### Loading the Flutter library

### 加载 Flutter 库

After it's found, the engine's shared libraries are memory loaded
once per process.

找到后，引擎的共享库将在每个进程中加载一次内存。

On **Android**, this also happens when the
[`FlutterEngine`][android-engine] is constructed because the
JNI connectors need to reference the Flutter C++ library.
On **iOS**, this happens when the
[`FlutterEngine`][ios-engine] is first run,
such as by running [`runWithEntrypoint:`][].

在 **Android** 上，当构建 
[`FlutterEngine`][android-engine] 
时也会发生这种情况，因为 JNI 连接器需要引用 Flutter C++ 库。
在 **iOS** 上，这是在首次运行 
[`FlutterEngine`][ios-engine] 时发生的，
例如运行 [`runWithEntrypoint:`][]。

### Starting the Dart VM

### 启动 Dart VM

The Dart runtime is responsible for managing Dart memory and
concurrency for your Dart code. In JIT mode,
it's additionally responsible for compiling
the Dart source code into machine code during runtime.

Dart 运行时负责管理 Dart 代码的 Dart 内存与异步。
在 JIT 模式下，它还负责在运行时将 Dart 源代码编译为机器码。

A single Dart runtime exists per application session on
Android and iOS.

在 Android 和 iOS 上，每个应用程序会话都存在一个 Dart 运行时。

A one-time Dart VM start is done when constructing the
[`FlutterEngine`][android-engine] for the first time on
**Android** and when [running a Dart entrypoint][ios-engine]
for the first time on **iOS**.

在 **Android** 上首次构建 
[`FlutterEngine`][android-engine]，
以及在 **iOS** 上首次
[运行 Dart 入口][ios-engine]
时，将完成一次 Dart VM 启动。

At this point, your Dart code's [snapshot][]
is also loaded into memory from your application's files.

此时，你的 Dart 代码的 [snapshot][] 
也将从应用程序的文件加载到内存中。

This is a generic process that also occurs if you used the
[Dart SDK][] directly, without the Flutter engine.

即使你直接使用 [Dart SDK][]而没 Flutter 引擎，也会这样执行，这是一个通用的过程。

The Dart VM never shuts down after it's started.

Dart VM 启动后永远不会关闭。

### Creating and running a Dart Isolate

### 创建并运行一个 Dart Isolate

After the Dart runtime is initialized,
the Flutter engine's usage of the Dart
runtime is the next step.

在初始化 Dart 运行时之后，下一步就是 Flutter 引擎对 Dart 运行时的使用。

This is done by starting a [Dart `Isolate`][] in the Dart runtime.
The isolate is Dart's container for memory and threads.
A number of [auxiliary threads][] on the host platform are
also created at this point to support the isolate, such
as a thread for offloading GPU handling and another for image decoding.

这是通过在 Dart 运行时中启动 
[Dart `Isolate`][] 来完成的。
isolate 是 Dart 的内存和线程容器。 
此时在宿主平台上还创建了许多
[辅助线程][auxiliary threads] 来支持 isolate，
例如用于解除 GPU 处理的线程和用于图像解码的线程。

One isolate exists per `FlutterEngine` instance, and multiple isolates
can be hosted by the same Dart VM.

每个 `FlutterEngine` 实例都存在一个 isolate，并且同一个 Dart VM 可以承载多个 isolate。

On **Android**, this happens when you call
[`DartExecutor.executeDartEntrypoint()`][]
on a `FlutterEngine` instance.

在 **Android** 上，当你在 `FlutterEngine` 实例上调用 
[`DartExecutor.executeDartEntrypoint()`][] 时，就会发生这种情况。

On **iOS**, this happens when you call [`runWithEntrypoint:`][]
on a `FlutterEngine`.

在 **iOS** 上，当你对 `FlutterEngine` 实例调用 [`runWithEntrypoint:`][]时会发生这种情况。

At this point, your Dart code's selected entrypoint
(the `main()` function of your Dart library's `main.dart` file,
by default) is executed. If you called the
Flutter function [`runApp()`][] in your `main()` function,
then your Flutter app or your library's widget tree is also created
and built. If you need to prevent certain functionalities from executing
in your Flutter code, then the `AppLifecycleState.detached`
enum value indicates that the `FlutterEngine` isn't attached
to any UI components such as a `FlutterViewController`
on iOS or a `FlutterActivity` on Android.

此时，Dart 代码会执行默认的入口点方法 (默认是 `main.dart` 文件的 `main()` 方法) ，
如果你在 `main()` 方法中调用 Flutter 的 [`runApp()`][] 方法，则你的 Flutter 应用
或库的 widget 树将会创建并构建。如果你需要阻止某些功能在 Flutter 代码中执行，
则需要使用枚举值 `AppLifecycleState.detached` 表示其不绑定在任何 UI 组件上。

### Attaching a UI to the Flutter engine

### 将 UI 挂载到 Flutter 引擎

A standard, full Flutter app moves to reach this state as
soon as the app is launched.

启动后不久，一个标准的完整的 Flutter 应用程序便会达到此状态。

In an add-to-app scenario,
this happens when you attach a `FlutterEngine`
to a UI component such as by calling [`startActivity()`][]
with an [`Intent`][] built using [`FlutterActivity.withCachedEngine()`][]
on **Android**. Or, by presenting a [`FlutterViewController`][]
initialized by using [`initWithEngine: nibName: bundle:`][]
on **iOS**.

在 add-to-app 的场景中，
例如通过在 **Android** 上使用 [`FlutterActivity.withCachedEngine()`][] 
方法构建的 [`Intent`][]，
调用 [`startActivity()`][] 时，
或者，在 **iOS** 上调用 [`initWithEngine: nibName: bundle:`][]，
展示实例化的 [`FlutterViewController`][]，
都会将 `FlutterEngine` 挂载到 UI 组件。

This is also the case if a Flutter UI component was launched without
pre-warming a `FlutterEngine` such as with
[`FlutterActivity.createDefaultIntent()`][] on **Android**,
or with [`FlutterViewController initWithProject: nibName: bundle:`][]
on **iOS**. An implicit `FlutterEngine` is created in these cases.

如果在没有启动 Flutter UI 组件的情况下也是如此,
例如在 **Android** 上使用 [`FlutterActivity.createDefaultIntent()`][] 
或在 **iOS** 上使用 [`FlutterViewController initWithProject: nibName: bundle:`][] 
预热一个 `FlutterEngine`。
在这些情况下，将创建一个隐式的 `FlutterEngine`。

Behind the scene, both platform's UI components provide the
`FlutterEngine` with a rendering surface such as a
[`Surface`][] on **Android** or a [CAEAGLLayer][] or [CAMetalLayer][]
on **iOS**.

在后台，这两个平台的UI组件都为 `FlutterEngine` 提供了渲染层，
例如 **Android** 上的 [`Surface`][] 或 **iOS** 上的 [CAEAGLLayer][]
或 [CAMetalLayer][]。

At this point, the [`Layer`][] tree generated by your Flutter
program, per frame, is converted into
OpenGL (or Vulkan or Metal) GPU instructions.

此时，你的 Flutter 程序生成的 [`Layer`][]
树将转换为 OpenGL（或 Vulkan 或 Metal）GPU 指令。

[android-engine]: https://api.flutter-io.cn/javadoc/io/flutter/embedding/engine/FlutterEngine.html
[auxiliary threads]: https://github.com/flutter/flutter/blob/main/docs/about/The-Engine-architecture.md#threading
[CAEAGLLayer]: https://developer.apple.com/documentation/quartzcore/caeagllayer
[CAMetalLayer]: https://developer.apple.com/documentation/quartzcore/cametallayer
[Dart `Isolate`]: https://api.dart.cn/dart-isolate/Isolate-class.html
[Dart SDK]: https://dart.cn/tools/sdk
[`DartExecutor.executeDartEntrypoint()`]: https://api.flutter-io.cn/javadoc/io/flutter/embedding/engine/dart/DartExecutor.html#executeDartEntrypoint-io.flutter.embedding.engine.dart.DartExecutor.DartEntrypoint-
[`FlutterActivity.createDefaultIntent()`]: https://api.flutter-io.cn/javadoc/io/flutter/embedding/android/FlutterActivity.html#createDefaultIntent-android.content.Context-
[`FlutterActivity.withCachedEngine()`]: https://api.flutter-io.cn/javadoc/io/flutter/embedding/android/FlutterActivity.html#withCachedEngine-java.lang.String-
[`FlutterViewController`]: https://api.flutter-io.cn/ios-embedder/interface_flutter_view_controller.html
[`FlutterViewController initWithProject: nibName: bundle:`]: https://api.flutter-io.cn/ios-embedder/interface_flutter_view_controller.html#aa3aabfb89e958602ce6a6690c919f655
[`initWithEngine: nibName: bundle:`]: https://api.flutter-io.cn/ios-embedder/interface_flutter_view_controller.html#a0aeea9525c569d5efbd359e2d95a7b31
[`Intent`]: https://developer.android.google.cn/reference/android/content/Intent.html
[ios-engine]: https://api.flutter-io.cn/ios-embedder/interface_flutter_engine.html
[`Layer`]: https://api.flutter-io.cn/flutter/rendering/Layer-class.html
[multiple Flutters]: /add-to-app/multiple-flutters
[`runApp()`]: https://api.flutter-io.cn/flutter/widgets/runApp.html
[`runWithEntrypoint:`]: https://api.flutter-io.cn/ios-embedder/interface_flutter_engine.html#a019d6b3037eff6cfd584fb2eb8e9035e
[snapshot]: https://github.com/dart-lang/sdk/wiki/Snapshots
[`startActivity()`]: https://developer.android.google.cn/reference/android/content/Context#startActivity(android.content.Intent)
[`Surface`]: https://developer.android.google.cn/reference/android/view/Surface

