Flutter Embedder 的启动流程分析

259 阅读5分钟

在 Flutter 的架构中,Embedder 是连接 Flutter 引擎(Engine)和原生平台的桥梁。它负责将 Flutter 嵌入到不同的平台(如 Android、iOS、Windows、Linux 等),并处理窗口管理、输入事件、生命周期控制等与原生系统相关的任务。Embedder 的启动流程是 Flutter 应用运行的基础,贯穿了资源加载、引擎初始化、渲染视图创建等多个环节。

下面我们详细分析 Embedder 的启动流程。


1. Embedder 的职责

在启动过程中,Embedder 的主要职责包括:

  1. 加载和初始化 Flutter 引擎(Engine)
    • 加载 Flutter 的共享库(如 libflutter.so)。
    • 初始化引擎运行时环境,包括 Dart VM 和渲染管道。
  2. 资源加载
    • 提取和加载 Flutter 应用的资源文件(如 Dart 代码、图片等)。
  3. 窗口管理和渲染
    • 创建窗口和渲染表面(Surface),用于显示 Flutter 的 UI。
  4. 输入事件处理
    • 捕获原生平台的输入事件(如触摸、键盘)并传递给 Flutter 引擎。
  5. 生命周期管理
    • 处理应用的启动、暂停、恢复、销毁等生命周期事件。

2. Embedder 启动流程概览

Embedder 的启动流程可以分为以下几个阶段:

  1. 资源初始化:加载 Flutter 的共享库和应用资源。
  2. Flutter 引擎初始化:创建并配置 FlutterEngine
  3. 渲染视图初始化:创建用于显示 Flutter UI 的渲染视图(如 FlutterSurfaceView)。
  4. Dart 代码执行:加载 Dart 入口文件并启动 Flutter 框架。
  5. 运行与渲染:启动渲染循环,显示 Flutter 的首帧。

3. 启动流程的详细分析

3.1 资源初始化

  • 入口FlutterLoader.startInitialization 方法(Android 平台)。

  • 关键任务

    1. 加载 Flutter 的共享库
      • 在 Android 平台,通过 System.loadLibrary("flutter") 加载 libflutter.so
      • 在 iOS 平台,libflutter.dylib 是直接链接的,无需显式加载。
    2. JNI 接口绑定
      • 加载共享库后,会调用 JNI_OnLoad 方法,完成 JNI 接口的注册和绑定。
    3. 资源提取
      • 使用 ResourceExtractor 提取 Flutter 应用的资源文件(如 Dart AOT 文件、图片等),并将其存储到本地目录。
  • 关键代码(Android 平台)

public void startInitialization(Context applicationContext) {
    System.loadLibrary("flutter");
    ResourceExtractor.extractResources(applicationContext);
}

3.2 Flutter 引擎初始化

  • 入口FlutterActivityAndFragmentDelegate.onAttach 方法。

  • 关键任务

    1. 创建 FlutterEngine
      • 如果指定了缓存的引擎 ID,则从缓存中获取引擎实例。
      • 如果未指定缓存,则直接创建新的 FlutterEngine 实例。
    2. 初始化 FlutterJNI
      • 调用 FlutterJNI.attachToJni 方法,将 JNI 层与 Dart VM 绑定。
    3. 配置引擎
      • 初始化 PlatformPlugin,为 Flutter 提供剪贴板、输入法等原生能力。
      • 配置通道(如 MethodChannelEventChannel)以支持原生交互。
  • 关键代码(Android 平台)

FlutterEngine flutterEngine = new FlutterEngine(context);
flutterEngine.getDartExecutor().executeDartEntrypoint(
    DartExecutor.DartEntrypoint.createDefault()
);

3.3 渲染视图初始化

  • 入口FlutterActivityAndFragmentDelegate.onCreateView 方法。

  • 关键任务

    1. 创建渲染视图
      • 根据渲染模式(RenderMode)创建对应的 RenderSurface
      • 渲染模式包括:
        • FlutterSurfaceView(默认模式,基于 Surface 渲染)。
        • FlutterTextureView(基于 Texture 渲染)。
        • FlutterImageView(基于 Image 渲染)。
    2. 绑定 Flutter 引擎
      • 调用 FlutterView.attachToFlutterEngine 方法,将渲染视图与 FlutterEngine 绑定。
    3. 注册首帧回调
      • 注册 flutterUiDisplayListener,监听 Flutter UI 的首帧渲染完成事件。
  • 关键代码

FlutterView flutterView = new FlutterView(context);
flutterView.attachToFlutterEngine(flutterEngine);

3.4 Dart 代码执行

  • 入口FlutterActivityAndFragmentDelegate.doInitialFlutterViewRun 方法。

  • 关键任务

    1. 设置初始路由
      • 通过 NavigationChannel 设置 Dart 框架的初始页面路由。
    2. 加载 Dart 入口文件
      • 调用 DartExecutor.executeDartEntrypoint 方法,指定 Dart 的入口文件和函数。
    3. 启动 Dart 框架
      • 通过 JNI 调用 nativeRunBundleAndSnapshotFromLibrary 方法,加载 Dart 代码并启动 Flutter 框架。
  • 关键代码

flutterEngine.getNavigationChannel().setInitialRoute("/");
flutterEngine.getDartExecutor().executeDartEntrypoint(
    DartExecutor.DartEntrypoint.createDefault()
);

3.5 运行与渲染

  • 入口FlutterJNI.onSurfaceChangedFlutterJNI.onDrawFrame
  • 关键任务
    1. 启动渲染循环
      • Flutter 引擎会启动一个渲染循环,每帧都会调用 onDrawFrame 方法。
    2. 显示首帧
      • 当 Flutter 框架完成首帧绘制时,会通过 JNI 通知 Embedder。
      • Embedder 将渲染结果显示到屏幕上。

4. 启动流程总结

以下是 Flutter Embedder 启动流程的完整结构:

1. 资源初始化
   └── 加载 libflutter.so
   └── 提取 Flutter 应用资源

2. Flutter 引擎初始化
   └── 创建 FlutterEngine
   └── 初始化 FlutterJNI
   └── 配置 PlatformPlugin 和通道

3. 渲染视图初始化
   └── 创建渲染视图(FlutterSurfaceView 等)
   └── 绑定 FlutterEngine
   └── 注册首帧回调

4. Dart 代码执行
   └── 设置初始路由
   └── 加载 Dart 入口文件
   └── 启动 Flutter 框架

5. 运行与渲染
   └── 启动渲染循环
   └── 显示首帧

5. 关键点分析

  1. 资源加载

    • 资源加载是启动流程的第一步,确保 Flutter 应用的资源(如 Dart AOT 文件)能够被正确加载。
  2. FlutterEngine 的核心作用

    • FlutterEngine 是整个 Flutter 应用的核心,它连接了 Dart VM 和渲染管道。
    • 它的初始化过程决定了应用的运行环境。
  3. 渲染视图的选择

    • 根据不同的渲染模式(FlutterSurfaceViewFlutterTextureView 等),可以适配不同的场景需求。
  4. 高效的渲染机制

    • Flutter 的渲染是基于 Vsync 信号的,这确保了渲染与屏幕刷新同步,从而提供流畅的用户体验。

6. 总结

Flutter Embedder 的启动流程是整个 Flutter 应用运行的基础,它将原生平台与 Flutter 引擎无缝连接,确保 Dart 代码和渲染逻辑能够正确运行。通过对启动流程的深入理解,我们可以更好地优化应用的启动性能,并解决与引擎交互的相关问题。

无论是资源加载、引擎初始化还是渲染视图的创建,每个环节都至关重要。掌握这些细节,不仅有助于开发高性能的 Flutter 应用,还能帮助我们更好地理解 Flutter 的跨平台能力和运行机制。