Flutter App启动流程分析

Posted Beason_H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter App启动流程分析相关的知识,希望对你有一定的参考价值。

首先手动创建一个hello_project的Flutter Project,再一步步跟着源码走

按照惯例我们首先查找是否有自定义的Application,发现Flutter Project没有自定义Application,然后我们再来看MainActivity.kt

class MainActivity: FlutterActivity() {
}

MainActivity代码无比简单,我们继续看FlutterActivity.java(Google官方都推Kotlin了,FlutterActivity居然还用Java…)

public class FlutterActivity extends Activity
    implements FlutterActivityAndFragmentDelegate.Host, LifecycleOwner 

MainActivity直接继承自Activity,同时实现了两个接口:LifecycleOwner(暴露绑定生命周期的方法),FlutterActivityAndFragmentDelegate.Host,这里的Host主要是FlutterActivity作为宿主提供暴露各种方法,Host接口方法命名都比较简单直观,这里不做详细解释。

再来看onCreate方法

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    switchLaunchThemeForNormalTheme();
    super.onCreate(savedInstanceState);
		// 创建delegate,重点后面分析
    delegate = new FlutterActivityAndFragmentDelegate(this);
    // 1、onAttach 重点,内部初始化引擎逻辑
    delegate.onAttach(this);
    //onRestoreInstanceState,类似Activity中的onRestoreInstanceState方法,可以用来恢复数据
    delegate.onRestoreInstanceState(savedInstanceState);

    //绑定生命周期
    lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);

    configureWindowForTransparency();
    //2、创建FlutterView,显示到Activity上
    setContentView(createFlutterView());
    configureStatusBarForFullscreenFlutterExperience();
  }

这里我们重点关注两步

  1. onAttach 内部创建初始化引擎
  2. createFlutterView() 创建FlutterView显示到Activity上

下面着重一步一步来分析

onAttach

  void onAttach(@NonNull Context context) {
    ensureAlive();

    // 是否已经初始化过引擎
    if (flutterEngine == null) {
      //下面重点分析引擎初始化
      setupFlutterEngine();
    }

    if (host.shouldAttachEngineToActivity()) {
      //engine 与 activity绑定
      Log.v(TAG, "Attaching FlutterEngine to the Activity that owns this delegate.");
      flutterEngine.getActivityControlSurface().attachToActivity(this, host.getLifecycle());
    }

    //初始化平台插件,本质上,是将engine的 channel回调与平台的系统服务进行绑定,如:震动、复制粘贴、声音播放等...
    platformPlugin = host.providePlatformPlugin(host.getActivity(), flutterEngine);

    //注册插件,通过反射调用 “io.flutter.plugins.GeneratedPluginRegistrant.registerWith()”
    host.configureFlutterEngine(flutterEngine);
  }

setupFlutterEngine()

@VisibleForTesting
void setupFlutterEngine() {
    // 返回FlutterEngine,如果为空会自动创建一个Engine
    flutterEngine = host.provideFlutterEngine(host.getContext());
    if (flutterEngine != null) {
      isFlutterEngineFromHost = true;
      return;
    }
    // 如果上面步骤都没后获取到flutterEngine的话,就创建一个FlutterEngine
    flutterEngine =
        new FlutterEngine(
            host.getContext(),
            host.getFlutterShellArgs().toArray(),
            /*automaticallyRegisterPlugins=*/ false,
            /*willProvideRestorationData=*/ host.shouldRestoreAndSaveState());
    isFlutterEngineFromHost = false;
  }

我们先来看一下FlutterEngine的理解:

  1. 是一个独立的Flutter执行环境
  2. FlutterEngine 是一个容器,通过它可以在 android 应用程序中运行 Dart 代码。
  3. FlutterEngine 中的 Dart 代码可以在后台执行,也可以使用附带的 FlutterRenderer 和 Dart 代码将 Dart 端 UI 效果渲染到屏幕上,渲染可以开始和停止,从而允许 FlutterEngine 从 UI 交互转移到仅进行数据处理,然后又返回到 UI 交互的能力。
  4. 可能同时存在多个FlutterEngine执行Dart代码,并且在单个Android应用程序中绘制UI。为了更好的内存性能特性,通过FlutterEngineGroup构造多个FlutterEngine,而不是直接通过FlutterEngine的构造函数。
  5. 使用 FlutterEngine 执行 Dart 或 Flutter 代码需要先通过 FlutterEngine 获取 DartExecutor 引用,然后调用 DartExecutor 的executeDartEntrypoint(DartExecutor.DartEntrypoint)执行 Dart 代码即可,同一个 FlutterEngine 实例中获取的 DartExecutor 的executeDartEntrypoint(DartExecutor.DartEntrypoint)方法只能被调用一次。
  6. 要开始将 Flutter 内容渲染到屏幕上,请使用 getRenderer() 获取 FlutterRenderer,然后附加一个 RenderSurface。 考虑使用 FlutterView 作为 RenderSurface。
  7. App 每个进程中创建第一个 FlutterEngine 实例的时候会加载 Flutter 引擎的原生库并启动 Dart VM(VM 存活生命周期跟随进程),随后同进程中其他的 FlutterEngines 将在同一个 VM 实例上运行,但在运行 DartExecutor 时将拥有自己的 Dart Isolate。每个 Isolate 都是一个独立的 Dart 环境,除非通过 Isolate 端口,否则无法相互通信。
  8. App 每个进程中创建第一个 FlutterEngine 实例的时候会加载 Flutter 引擎的原生库并启动 Dart VM(VM 存活生命周期跟随进程),随后同进程中其他的 FlutterEngine 将在同一个 VM 实例上运行,但在运行 DartExecutor 时将拥有自己的 Dart Isolate。每个 Isolate 都是一个独立的 Dart 环境,除非通过 Isolate 端口,否则无法相互通信。

最终整理对于一个多FlutterEngine的App来说,FlutterEngine,DartExecutor,Dart VM, Isloate关系如下:

接下来我们继续看FlutterEngine

public class FlutterEngine {
  //Flutter C/C++与平台java层接口定义交互。Flutter 的引擎是用 C/C++ 构建的。 Android Flutter 嵌入负责协调 Android 操作系统事件和应用程序用户与 C/C++ 引擎的交互。
  @NonNull private final FlutterJNI flutterJNI;
  //表示 FlutterEngine 的渲染职责。
	//FlutterRenderer 与提供的 RenderSurface 协同工作,将 Flutter 像素绘制到 Android 视图层次结构。
	//FlutterRenderer 管理用于渲染的纹理,并通过 JNI 将一些 Java 调用转发到原生 Flutter 代码。 相应的 RenderSurface 提供此渲染器绘制的 Android Surface。
	//io.flutter.embedding.android.FlutterSurfaceView 和 io.flutter.embedding.android.FlutterTextureView 是 RenderSurface 的实现
  @NonNull private final FlutterRenderer renderer;
  //Dart执行器。
  @NonNull private final DartExecutor dartExecutor;
  //用来管理安卓组件和Flutter plugins插件。
  @NonNull private final FlutterEngineConnectionRegistry pluginRegistry;
  //localization的安卓端实现插件。
  @NonNull private final LocalizationPlugin localizationPlugin;

  //一堆系统通道。负责与系统底层通信
  @NonNull private final AccessibilityChannel accessibilityChannel;
  @NonNull private final DeferredComponentChannel deferredComponentChannel;
  @NonNull private final KeyEventChannel keyEventChannel;
  @NonNull private final LifecycleChannel lifecycleChannel;
  @NonNull private final LocalizationChannel localizationChannel;
  @NonNull private final MouseCursorChannel mouseCursorChannel;
  @NonNull private final NavigationChannel navigationChannel;
  @NonNull private final RestorationChannel restorationChannel;
  @NonNull private final PlatformChannel platformChannel;
  @NonNull private final SettingsChannel settingsChannel;
  @NonNull private final SystemChannel systemChannel;
  @NonNull private final TextInputChannel textInputChannel;

  // Platform Views.
  // 管理平台视图。每个 io.flutter.app.FlutterPluginRegistry 都有一个平台视图控制器。 一个平台视图控制器最多可以附加到一个 Flutter 视图
  @NonNull private final PlatformViewsController platformViewsController;
  // Engine Lifecycle.
  // 引擎声明周期监听
  @NonNull private final Set<EngineLifecycleListener> engineLifecycleListeners = new HashSet<>();
  //......

  //全参数的构造函数,各种构造最终都走进这里
  public FlutterEngine(
      @NonNull Context context,
      @Nullable FlutterLoader flutterLoader,
      @NonNull FlutterJNI flutterJNI,
      @NonNull PlatformViewsController platformViewsController,
      @Nullable String[] dartVmArgs,
      boolean automaticallyRegisterPlugins,
      boolean waitForRestorationData) {
    //......
    //创建一个DartExecutor并将flutterJNI和安卓平台的assetManager实例传递进去。
    this.dartExecutor = new DartExecutor(flutterJNI, assetManager);
    this.dartExecutor.onAttachedToJNI();
    //......
    //各种channel实例化
    accessibilityChannel = new AccessibilityChannel(dartExecutor, flutterJNI);
    deferredComponentChannel = new DeferredComponentChannel(dartExecutor);
    keyEventChannel = new KeyEventChannel(dartExecutor);
    lifecycleChannel = new LifecycleChannel(dartExecutor);
    localizationChannel = new LocalizationChannel(dartExecutor);
    mouseCursorChannel = new MouseCursorChannel(dartExecutor);
    navigationChannel = new NavigationChannel(dartExecutor);
    platformChannel = new PlatformChannel(dartExecutor);
    restorationChannel = new RestorationChannel(dartExecutor, waitForRestorationData);
    settingsChannel = new SettingsChannel(dartExecutor);
    systemChannel = new SystemChannel(dartExecutor);
    textInputChannel = new TextInputChannel(dartExecutor);
    //......
    //插件实例化。
    this.localizationPlugin = new LocalizationPlugin(context, localizationChannel);

    this.flutterJNI = flutterJNI;
    if (flutterLoader == null) {
      flutterLoader = FlutterInjector.instance().flutterLoader();
    }
    //......
		// 引擎与四大组件的桥梁
    this.pluginRegistry =
        new FlutterEngineConnectionRegistry(context.getApplicationContext(), this, flutterLoader);
	//默认就是自动注册plugins的,可以通过清单文件配置变更等。
    if (automaticallyRegisterPlugins && flutterLoader.automaticallyRegisterPlugins()) {
      registerPlugins();
    }
  }
  //......

  //注册flutter项目根目录下pubspec.yaml中依赖的所有flutter plugins。
  //Flutter tool会生成一个GeneratedPluginRegistrant的类。
  private void registerPlugins() {
    try {
      Class<?> generatedPluginRegistrant = Class.forName("io.flutter.plugins.GeneratedPluginRegistrant");
      Method registrationMethod = generatedPluginRegistrant.getDeclaredMethod("registerWith", FlutterEngine.class);
      registrationMethod.invoke(null, this);
    } catch (Exception e) {
      Log.w(TAG, "Tried to automatically register plugins with FlutterEngine ("
              + this + ") but could not find and invoke the GeneratedPluginRegistrant.");
    }
  }
  //......省略一堆属性成员的get方法
}

总结下Flutter主要作用:

  1. FlutterEngineConnectionRegistry:创建组件与四大引擎生命周期的桥梁,方便插件根据各个组件的生命周期处理
  2. registerPlugins:通过反射注册自定义插件
  3. 各种Channel的初始化,建立引擎与平台系统之间的桥梁
  4. DartExecutor:Dart执行环境创建,onAttachedToJNI之后,DartExecutor将开始处理与Dart上下文之间的双向通行,BinaryMessenger(向Dart发送消息),PlatformMessageHandler,它接受来自Dart的消息
  5. FlutterRenderer:渲染环境的创建

到此FlutterEngine基本创建完成,内部细节不做详解。下面再来分析下createFlutterView

createFlutterView

createFlutterView走到了FlutterActivityAndFragmentDelegate的onCreateView方法

 @NonNull
  View onCreateView(
      LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    Log.v(TAG, "Creating FlutterView.");
    ensureAlive();

    if (host.getRenderMode() == RenderMode.surface) {
      FlutterSurfaceView flutterSurfaceView =
          new FlutterSurfaceView(
              host.getActivity(), host.getTransparencyMode() == TransparencyMode.transparent);

      // 允许自定义flutterSurfaceView
      host.onFlutterSurfaceViewCreated(flutterSurfaceView);

      // 创建拥有 FlutterSurfaceView 的 FlutterView。
      flutterView = new FlutterView(host.getActivity(), flutterSurfaceView);
    } else {
      FlutterTextureView flutterTextureView = new FlutterTextureView(host.getActivity());

      // 允许自定义flutterTextureView
      host.onFlutterTextureViewCreated(flutterTextureView);

      // 创建拥有 FlutterTextureView 的 FlutterView。
      flutterView = new FlutterView(host.getActivity(), flutterTextureView);
    }

    // 添加侦听器以在 Flutter 呈现其第一帧时收到通知。
    flutterView.addOnFirstFrameRenderedListener(flutterUiDisplayListener);

    flutterSplashView = new FlutterSplashView(host.getContext());
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
      flutterSplashView.setId(View.generateViewId());
    } else {
      flutterSplashView.setId(486947586);
    }
    flutterSplashView.displayFlutterViewWithSplash(flutterView, host.provideSplashScreen());

    Log.v(TAG, "Attaching FlutterEngine to FlutterView.");
    flutterView.attachToFlutterEngine(flutterEngine);
    return flutterSplashView;
  }

该方法主要完成四个任务:

  1. 在 View 层次结构中创建一个新的 FlutterView
  2. 添加一个 FlutterUiDisplayListener
  3. 将 FlutterEngine 附加到新的 FlutterView
  4. flutterSplashView(主要作用是在 FlutterView render 渲染出来之前显示一个SplashScreen),类似于过度图

我们在简单看下FlutterView,FlutterView是一个Android 原生的控件,继承自FrameLayout,它之所以显示的是Flutter UI,完全是依赖于FlutterSurfaceView和FlutterTextureView,而FlutterSurfaceView和FlutterTextureView这两个View的绘制内容又是来自于FlutterEngine提供。

FlutterView源码分析,我们后面再来单独讲…

结尾

​ 讲到这里,我们基本上了解了Flutter启动的大致流程。其实无论是FlutterActivity还是FlutterFragment都是通过代理类FlutterActivityAndFragmentDelegate来封装调用Flutter的各种行为。

​ 下文我们在一起看看FlutterView是如何工作,Flutter UI是如何显示到原生界面上的。。。。

以上是关于Flutter App启动流程分析的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 启动流程简析 | 开发者说·DTalk

2021-12-23 flutter module源码方式集成流程分析

APP启动流程及分析APP启动性能的方法!

Android 桌面应用启动APP的流程

Android 桌面应用启动APP的流程

关于Flutter初始化流程,我必须告诉你的是...