Flutter源码阅读分析:引擎初始化与启动

引擎初始化与启动


0. 前言

Flutter是当前比较火热的前端开发框架,正好我最近也在作和Flutter引擎相关的工做,就顺手研究一下Flutter的源码。
源码主要分为两部分:前端

  • Engine,是可供Flutter宿主应用提供的一个可移植运行时。Engine实现了Flutter的核心库,包括动画、图形、文件、网络I/O、访问支持、插件架构和Dart的运行时、编译工具链;
  • Flutter Framework,大部分的Flutter开发者主要经过Flutter Framework交互。Framework提供了一个现代的、可交互的框架,以及一个丰富的平台、布局、基础部件的集合。

Flutter官方源码下载路径:
engine: https://github.com/flutter/engine
flutter framework: https://github.com/flutter/flutterjava

本文主要分析引擎的初始化流程和启动流程。android


1. 初始化流程

1.1 Android平台适配层

众所周知,Android应用的入口基本都是Activity,那么咱们就先从Flutter的Activity开始着手分析。git

1.1.1 FlutterActivity

Engine中存在两个FlutterActivity(shell/platform/android/io/flutter/app/FlutterActivity.javashell/platform/android/io/flutter/embedding/android/FlutterActivity.java),其中在2020年5月13日的代码提交中,前一个FlutterActivity注释修改成废弃Activity基类。因此如今可用的Activity基类是后一个。
根据FlutterActivity的注释,咱们可知:
FlutterActivity是将Flutter集成到Android应用中的最简单最直接的方式,用于显示一个全屏的Flutter UI。主要职责是:github

  • 显示一个Android的lauch screen;
  • 显示Flutter的splash screen;
  • 设置状态栏;
  • 选择Dart执行应用包路径和入口点;
  • 选择Flutter的初始化路由;
  • 若是须要的话,渲染透明度;
  • 提供子类钩子,提供和配置FlutterEngine。

先从FlutterActivity定义看起:web

public class FlutterActivity extends Activity
    implements FlutterActivityAndFragmentDelegate.Host, LifecycleOwner

FlutterActivity继承于ActivityFlutterActivityAndFragmentDelegate.Host接口是在FlutterActivityAndFragmentDelegateFlutterActivity持有类。shell

ActivityonCreate方法是入口关键方法,看一下FlutterActivityonCreate方法:promise

// ./shell/platform/android/io/flutter/embedding/android/FlutterActivity.java
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) { 
 
  
  switchLaunchThemeForNormalTheme(); // 设置主题

  super.onCreate(savedInstanceState);

  lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE); // 设置Android生命周期

  delegate = new FlutterActivityAndFragmentDelegate(this); // [1]
  delegate.onAttach(this);
  delegate.onActivityCreated(savedInstanceState);

  configureWindowForTransparency(); // 设置背景透明模式
  setContentView(createFlutterView()); // [2]
  configureStatusBarForFullscreenFlutterExperience(); // 配置系统状态栏
}
  • [1] FlutterActivityAndFragmentDelegate类实现了FlutterActivityFlutterFragment之间相同的逻辑。
  • [2] 经过调用FlutterActivityAndFragmentDelegateonCreateView方法建立出FlutterView并将其添加到界面上。FlutterView用于在Android设备上显示Flutter UI。

1.1.2 FlutterActivityAndFragmentDelegate

下面就再分析一下FlutterActivityAndFragmentDelegate的源码逻辑:网络

// ./shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java
final class FlutterActivityAndFragmentDelegate { 
 
  
  ...
  FlutterActivityAndFragmentDelegate(@NonNull Host host) { 
 
  
    this.host = host; // 保存FlutterActivity对象
  }
  ...
  // [3]
  void onAttach(@NonNull Context context) { 
 
  
    ...
    setupFlutterEngine(); // 建立FlutterEngine
    ...
  }
  ...
  // [4]
  @NonNull
  View onCreateView(
      LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 
 
  
    ...
    // 建立FlutterSurfaceView,用于提供绘制Flutter UI的Surface
    FlutterSurfaceView flutterSurfaceView =
        new FlutterSurfaceView(
            host.getActivity(), host.getTransparencyMode() == TransparencyMode.transparent);
    ...
    flutterView = new FlutterView(host.getActivity(), flutterSurfaceView);
    ...
    flutterSplashView = new FlutterSplashView(host.getContext());
    ...
    flutterSplashView.displayFlutterViewWithSplash(flutterView, host.provideSplashScreen());
    flutterView.attachToFlutterEngine(flutterEngine);
    return 
  }
  ...
  return flutterSplashView;
}
  • [3] onAttach方法主要作了如下事情:1. 初始化Flutter系统;2. 获取或者建立一个FlutterEngine;3. 建立和配置PlatformPlugin;4. 将FlutterEngine附在Activity上;5. 经过HostconfigureFlutterEngine方法配置FlutterEngine
  • [4] 'onCreateView’方法主要作如下事情:1. 在View树中建立一个新的FlutterView;2. 在FlutterView中添加一个FlutterUiDisplayListener;3. 将FlutterEngine附着到FlutterView上;4. 返回这个新的View树。

在这里出现了两个比较重要的类,FlutterViewFlutterEngine架构

1.1.3 FlutterView

FlutterView的做用是将Flutter UI经过对应的FlutterEngine绘制后,显示在Android设备上。这里有两种渲染模式:surfacetexture
在通常状况,咱们都使用surface模式,即将Flutter UI绘制在SurfaceView上,这种模式拥有最优的性能,缺点是没法置于两个其余Android View的z-index之间,同时也没法动画化或者进行变换。
下面咱们看一下FlutterView的源码实现:

// ./shell/platform/android/io/flutter/embedding/android/FlutterView.java
public class FlutterView extends FrameLayout { 
 
  
  ...
  private FlutterView(
      @NonNull Context context,
      @Nullable AttributeSet attrs,
      @NonNull FlutterSurfaceView flutterSurfaceView) { 
 
  
    super(context, attrs);

    this.flutterSurfaceView = flutterSurfaceView;
    this.renderSurface = flutterSurfaceView;

    init();
  }
  ...
  private void init() { 
 
  
    ...
    addView(flutterSurfaceView);
    ...
    // FlutterView needs to be focusable so that the InputMethodManager can interact with it.
    setFocusable(true);
    setFocusableInTouchMode(true);
  }
  ...
  // 将当前FlutterView链接到给定的FLutterEngine
  // FlutterView将经过给定的FlutterEngine绘制UI,同时也将开始将后续的交互时间传递到FlutterEngine,
  // 例如触摸事件、键盘事件等。
  public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) { 
 
  
    ...
    this.flutterEngine = flutterEngine;
    // Instruct our FlutterRenderer that we are now its designated RenderSurface.
    FlutterRenderer flutterRenderer = this.flutterEngine.getRenderer();
    ...
    renderSurface.attachToRenderer(flutterRenderer); // [5]
    ...
    // Initialize various components that know how to process Android View I/O
    // in a way that Flutter understands.
    ...
    // Push View and Context related information from Android to Flutter.
    sendUserSettingsToFlutter();
    sendLocalesToFlutter(getResources().getConfiguration());
    sendViewportMetricsToFlutter();

    flutterEngine.getPlatformViewsController().attachToView(this); // PlatformViewsController获取当前FlutterView
    ...
  }
}
  • [5] 将FlutterSurfaceViewSurface提供给指定的FlutterRender,用于将Flutter UI绘制到当前的FlutterSurfaceView

1.1.4 FlutterEngine

FlutterEngine是一个独立的Flutter运行环境,是Dart代码运行在Android应用的容器。

// ./shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java
/** Fully configurable {@code FlutterEngine} constructor. */ 
public FlutterEngine(
    @NonNull Context context,
    @NonNull FlutterLoader flutterLoader,
    @NonNull FlutterJNI flutterJNI,
    @NonNull PlatformViewsController platformViewsController,
    @Nullable String[] dartVmArgs,
    boolean automaticallyRegisterPlugins) { 
 
  
  this.flutterJNI = flutterJNI;
  flutterLoader.startInitialization(context.getApplicationContext());
  ...
  attachToJni();
  this.dartExecutor = new DartExecutor(flutterJNI, context.getAssets());
  this.dartExecutor.onAttachedToJNI();
  this.renderer = new FlutterRenderer(flutterJNI);
  ...
  xxxChannel = new XxxChannel(...); // 建立各个消息通道,用于传递事件、消息
  ...
}

DartExecutor用于配置、启动、执行Dart代码,在后续分析中再详细研究。
FlutterActivityAndFragmentDelegatesetupFlutterEngine方法中调用的FlutterEngine构造方法没有传入FlutterJNI,在三参数构造方法中,会建立FlutterJNI对象,并传入全参数构造方法。FlutterJNI则是沟通Android的Java与Flutter引擎核心C++代码的桥梁。

1.1.5 FlutterJNI

FlutterJNI是Flutter内嵌Java代码和引擎C++代码之间的接口。
Flutter引擎的代码是使用C++实现的。Android Flutter嵌入则负责协调Android系统事件和应用用户交互事件。这些事件协调须要消息交流接口,这就须要用到JNI(Java Native Interface)来穿过Java/native边界。
在Flutter的设计中,全部的JNI接口都集中在FlutterJNI这个类中。这么作主要有如下几个缘由:

  • JNI调用都是静态的,且没有Java实现,所以没有理由将调用与不一样的类相关联;
  • 全部的JNI调用必须在C/C++代码中注册,当增长额外的包含JNI调用时,这个注册会变得很是复杂;
  • 不少Android开发者对native开发或者JNI不熟悉,所以在后续维护中减小JNI的接口是颇有必要的。

大部分FlutterJNI中的调用都与特定的“platform view”相关,而“platform view”的数量可能会不少。因此,在执行了attachToNative方法后,每一个FlutterJNI实例都持有一个本地“platform view”的ID,且这个ID与bendingC/C++引擎代码共享。这个ID会被传递到全部的具体platform view的本地方法。

// ./shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java
public class FlutterJNI { 
 
  
  ...
  public FlutterJNI() { 
 
  
    // We cache the main looper so that we can ensure calls are made on the main thread
    // without consistently paying the synchronization cost of getMainLooper().
    mainLooper = Looper.getMainLooper();
  }
  ...
  @UiThread
  public void attachToNative(boolean isBackgroundView) { 
 
  
    ensureRunningOnMainThread();
    ensureNotAttachedToNative();
    nativePlatformViewId = nativeAttach(this, isBackgroundView);
  }

  private native long nativeAttach(@NonNull FlutterJNI flutterJNI, boolean isBackgroundView);
  ...
}
// ./shell/platform/android/platform_view_android_jni.cc
bool RegisterApi(JNIEnv* env) { 
 
  
  static const JNINativeMethod flutter_jni_methods[] = { 
 
  
      { 
 
  
          .name = "nativeAttach",
          .signature = "(Lio/flutter/embedding/engine/FlutterJNI;Z)J",
          .fnPtr = reinterpret_cast<void*>(&AttachJNI),
      },
      ...
  };
  if (env->RegisterNatives(g_flutter_jni_class->obj(), flutter_jni_methods,
                           fml::size(flutter_jni_methods)) != 0) { 
 
  
    FML_LOG(ERROR) << "Failed to RegisterNatives with FlutterJNI";
    return false;
  }
  ...
}

static jlong AttachJNI(JNIEnv* env,
                       jclass clazz,
                       jobject flutterJNI,
                       jboolean is_background_view) { 
 
  
  fml::jni::JavaObjectWeakGlobalRef java_object(env, flutterJNI);
  auto shell_holder = std::make_unique<AndroidShellHolder>( // [6]
      FlutterMain::Get().GetSettings(), java_object, is_background_view);
  if (shell_holder->IsValid()) { 
 
  
    return reinterpret_cast<jlong>(shell_holder.release());
  } else { 
 
  
    return 0;
  }
}
  • [6] AndroidShellHolder是C/C++的Shell持有类。

1.1.6 AndroidShellHolder

AndroidShellHolder中保存有Flutter设置参数、FlutterJNI的Java引用、PlatformViewAndroid对象(该对象在后续建立)、Shell对象等。

// ./shell/platform/android/android_shell_holder.cc
AndroidShellHolder::AndroidShellHolder(
    flutter::Settings settings,
    fml::jni::JavaObjectWeakGlobalRef java_object,
    bool is_background_view)
    : settings_(std::move(settings)), java_object_(java_object) { 
 
  
  ...
  // 建立三个线程:UI线程、GPU线程、IO线程
  thread_host_ = { 
 
  thread_label, ThreadHost::Type::UI | ThreadHost::Type::GPU |
                                    ThreadHost::Type::IO};
  ...
  fml::WeakPtr<PlatformViewAndroid> weak_platform_view;
  Shell::CreateCallback<PlatformView> on_create_platform_view =
      [is_background_view, java_object, &weak_platform_view](Shell& shell) { 
 
  
        std::unique_ptr<PlatformViewAndroid> platform_view_android;
        ...
        platform_view_android = std::make_unique<PlatformViewAndroid>( // [7]
            shell,                   // delegate
            shell.GetTaskRunners(),  // task runners
            java_object,             // java object handle for JNI interop
            shell.GetSettings()
                .enable_software_rendering  // use software rendering
        ); 
        weak_platform_view = platform_view_android->GetWeakPtr();
        return platform_view_android;
      };
  ...
  // [8]
  shell_ =
      Shell::Create(task_runners,             // task runners
                    GetDefaultWindowData(),   // window data
                    settings_,                // settings
                    on_create_platform_view,  // platform view create callback
                    on_create_rasterizer      // rasterizer create callback
      );
  platform_view_ = weak_platform_view;
  ...
}
  • [7] 建立PlatformViewAndroid,该类继承于PlatformView。各平台会根据自身特色继承PlatformView类,实现自身平台的PlatformView
  • [8] 这里建立出了一个Shell对象,该类是Flutter引擎的关键类,此后的代码将于平台无关,为各个平台的通用代码。

1.2. 通用Shell层

1.2.1 Shell

Shell类是Flutter引擎中最重要的类之一。当嵌入应用建立了一个Flutter应用,都将建立一个Shell的实例,且嵌入者只持有一个Shell的unique指针。
Shell是Flutter应用的“中枢神经系统”,包含了多个组件,并继承它们相应的Delegate类。
下面看一下建立Shell的代码实现:

// ./shell/common/shell.cc
std::unique_ptr<Shell> Shell::Create(
    TaskRunners task_runners,
    const WindowData window_data,
    Settings settings,
    Shell::CreateCallback<PlatformView> on_create_platform_view,
    Shell::CreateCallback<Rasterizer> on_create_rasterizer) { 
 
  
  ...
  auto vm = DartVMRef::Create(settings); // 建立Dart虚拟机
  auto vm_data = vm->GetVMData();
  return Shell::Create(std::move(task_runners),        //
                       std::move(window_data),         //
                       std::move(settings),            //
                       vm_data->GetIsolateSnapshot(),  // isolate snapshot
                       on_create_platform_view,        //
                       on_create_rasterizer,           //
                       std::move(vm)                   //
  );
}

std::unique_ptr<Shell> Shell::Create(
    TaskRunners task_runners,
    const WindowData window_data,
    Settings settings,
    fml::RefPtr<const DartSnapshot> isolate_snapshot,
    const Shell::CreateCallback<PlatformView>& on_create_platform_view,
    const Shell::CreateCallback<Rasterizer>& on_create_rasterizer,
    DartVMRef vm) { 
 
  
  ...
  std::unique_ptr<Shell> shell;
  fml::TaskRunner::RunNowOrPostTask(
      task_runners.GetPlatformTaskRunner(),
      fml::MakeCopyable([&latch,                                          //
                         vm = std::move(vm),                              //
                         &shell,                                          //
                         task_runners = std::move(task_runners),          //
                         window_data,                                     //
                         settings,                                        //
                         isolate_snapshot = std::move(isolate_snapshot),  //
                         on_create_platform_view,                         //
                         on_create_rasterizer                             //
  ]() mutable { 
 
  
        shell = CreateShellOnPlatformThread(std::move(vm),
                                            std::move(task_runners),      //
                                            window_data,                  //
                                            settings,                     //
                                            std::move(isolate_snapshot),  //
                                            on_create_platform_view,      //
                                            on_create_rasterizer          //
        );
        ...
      }));
  return shell;
}

std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
    DartVMRef vm,
    TaskRunners task_runners,
    const WindowData window_data,
    Settings settings,
    fml::RefPtr<const DartSnapshot> isolate_snapshot,
    const Shell::CreateCallback<PlatformView>& on_create_platform_view,
    const Shell::CreateCallback<Rasterizer>& on_create_rasterizer) { 
 
  
  ...
  auto shell =
      std::unique_ptr<Shell>(new Shell(std::move(vm), task_runners, settings));

  // Create the rasterizer on the raster thread.
  fml::TaskRunner::RunNowOrPostTask(
      task_runners.GetRasterTaskRunner(), [&rasterizer_promise,  //
                                           &snapshot_delegate_promise,
                                           on_create_rasterizer,  //
                                           shell = shell.get()    //
  ]() { 
 
  
        std::unique_ptr<Rasterizer> rasterizer(on_create_rasterizer(*shell));
        ...
      });

  // Create the platform view on the platform thread (this thread).
  auto platform_view = on_create_platform_view(*shell.get());
  ...
  // Ask the platform view for the vsync waiter. This will be used by the engine
  // to create the animator.
  auto vsync_waiter = platform_view->CreateVSyncWaiter();
  ...
  // Create the IO manager on the IO thread.
  ...
  fml::TaskRunner::RunNowOrPostTask(
      io_task_runner,
      [&io_manager_promise,                                               //
       &weak_io_manager_promise,                                          //
       &unref_queue_promise,                                              //
       platform_view = platform_view->GetWeakPtr(),                       //
       io_task_runner,                                                    //
       is_backgrounded_sync_switch = shell->GetIsGpuDisabledSyncSwitch()  //
  ]() { 
 
  
        auto io_manager = std::make_unique<ShellIOManager>(
            platform_view.getUnsafe()->CreateResourceContext(),
            is_backgrounded_sync_switch, io_task_runner);
        ...
      });
  ...
  // Create the engine on the UI thread.
  ...
  fml::TaskRunner::RunNowOrPostTask(
      shell->GetTaskRunners().GetUITaskRunner(),
      fml::MakeCopyable([&engine_promise,                                 //
                         shell = shell.get(),                             //
                         &dispatcher_maker,                               //
                         &window_data,                                    //
                         isolate_snapshot = std::move(isolate_snapshot),  //
                         vsync_waiter = std::move(vsync_waiter),          //
                         &weak_io_manager_future,                         //
                         &snapshot_delegate_future,                       //
                         &unref_queue_future                              //
  ]() mutable { 
 
  
        const auto& task_runners = shell->GetTaskRunners();

        // The animator is owned by the UI thread but it gets its vsync pulses
        // from the platform.
        auto animator = std::make_unique<Animator>(*shell, task_runners,
                                                   std::move(vsync_waiter));

        engine_promise.set_value(std::make_unique<Engine>(
            *shell,                         //
            dispatcher_maker,               //
            *shell->GetDartVM(),            //
            std::move(isolate_snapshot),    //
            task_runners,                   //
            window_data,                    //
            shell->GetSettings(),           //
            std::move(animator),            //
            weak_io_manager_future.get(),   //
            unref_queue_future.get(),       //
            snapshot_delegate_future.get()  //
            ));
      }));
  if (!shell->Setup(std::move(platform_view),  //
                    engine_future.get(),       //
                    rasterizer_future.get(),   //
                    io_manager_future.get())   //
  ) { 
 
  
    return nullptr;
  }
  return shell;
}

从代码中能够看出,在platform线程中建立了Shell,以后分别在栅格化线程中建立Rasterizer,在platform线程中建立PlatformView,在IO线程中建立ShellIOManager,在UI线程中建立Engine,并将这四者设置到Shell中去。
Shell分别继承了四者的Delegate,四者经过相应的Delegate将事件传递到Shell
下面分别看一下这四个类。

1.2.2 PlatformView

在Android平台中,真正实现的是PlarformViewAndroid类,主要方法实现的功能都是在栅格化线程中对AndroidSurface进行操做。看一下NotifyCreated方法的实现:

// ./shell/platform/android/platform_view_android.cc
void PlatformViewAndroid::NotifyCreated(
    fml::RefPtr<AndroidNativeWindow> native_window) { 
 
  
  if (android_surface_) { 
 
  
    InstallFirstFrameCallback();
    ...
    fml::TaskRunner::RunNowOrPostTask(
        task_runners_.GetRasterTaskRunner(),
        [&latch, surface = android_surface_.get(),
         native_window = std::move(native_window)]() { 
 
  
          surface->SetNativeWindow(native_window);
          ...
        });
    ...
  }

  PlatformView::NotifyCreated(); // 此处调用了父类的对应方法
}
// ./shell/common/platform_view.cc
void PlatformView::NotifyCreated() { 
 
  
  std::unique_ptr<Surface> surface;
  auto* platform_view = this;
  ...
  fml::TaskRunner::RunNowOrPostTask(
      task_runners_.GetRasterTaskRunner(), [platform_view, &surface, &latch]() { 
 
  
        surface = platform_view->CreateRenderingSurface();
        ...
      });
  ...
  delegate_.OnPlatformViewCreated(std::move(surface));
}

主要实现的功能就是将native_window设置到surface中,再将这个surface通知到delegate(也就是Shell)中。也就是说,PlatformView主要起到一个沟通SurfaceShell的做用。

1.2.3 Rasterizer

RasterizerShell的一个组成部分,运行在GPU线程中。每一个Shell只能拥有一个Rasterizer实例。Rasterizer持有一个当前活动的在屏幕中显示的绘制SurfaceRasterizer在这个Surface上绘制从Engine中提交的layer tree。合成器上下文和屏上绘制SurfaceRasterizer的主要组成部分:合成器上下文包含绘制帧的全部必要的GPU状态。

on_create_rasterizer方法在AndroidShellHolder的构造方法中给出:

// ./shell/platform/android/android_shell_holder.cc
Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) { 
 
  
  return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
};
// ./shell/common/rasterizer.cc
Rasterizer::Rasterizer(Delegate& delegate, TaskRunners task_runners)
    : Rasterizer(delegate,
                 std::move(task_runners),
                 std::make_unique<flutter::CompositorContext>(
                     delegate.GetFrameBudget())) { 
 
  }

Rasterizer::Rasterizer(
    Delegate& delegate,
    TaskRunners task_runners,
    std::unique_ptr<flutter::CompositorContext> compositor_context)
    : delegate_(delegate),
      task_runners_(std::move(task_runners)),
      compositor_context_(std::move(compositor_context)),
      user_override_resource_cache_bytes_(false),
      weak_factory_(this) { 
 
  
  FML_DCHECK(compositor_context_);
}

在构造方法中建立了一个CompositorContext,这个类会在后续的文章中分析渲染机制时进行分析。

1.2.4 ShellIOManager

// ./shell/common/shell_io_manager.cc
class ShellIOManager final : public IOManager { 
 
  
  ...
  void NotifyResourceContextAvailable(sk_sp<GrContext> resource_context);
  void UpdateResourceContext(sk_sp<GrContext> resource_context);
  ...
  fml::WeakPtr<GrContext> GetResourceContext() const override;
  fml::RefPtr<flutter::SkiaUnrefQueue> GetSkiaUnrefQueue() const override;
}

ShellIOManager继承自IOManager类。IOManager是管理获取GrContext资源和Skia队列的方法的接口类。这二者都属于图形绘制相关内容,在后续文章中进行分析。
NotifyResourceContextAvailableUpdateResourceContext方法是通知GrContext建立和获取的方法。

1.2.5 Engine

Engine类是Shell的组成部分之一,运行于UI线程。其主要功能是管理根Isolate和它的运行时。每一个Shell只能拥有一个Engine实例。Flutter应用的根Isolate会获取“窗口”绑定。经过这些绑定,一个用能够调度帧、推送layer tree用于渲染、请求解压图片并提交到GPU等等。
Engine管理根Isolate的所有生命周期。当Engine被回收时,其持有者会认为根Isolate已经关闭且资源已经被回收。
下面看一下Engine的构造方法:

// ./shell/common/engine.cc
Engine::Engine(Delegate& delegate,
               const PointerDataDispatcherMaker& dispatcher_maker,
               DartVM& vm,
               fml::RefPtr<const DartSnapshot> isolate_snapshot,
               TaskRunners task_runners,
               const WindowData window_data,
               Settings settings,
               std::unique_ptr<Animator> animator,
               fml::WeakPtr<IOManager> io_manager,
               fml::RefPtr<SkiaUnrefQueue> unref_queue,
               fml::WeakPtr<SnapshotDelegate> snapshot_delegate)
    : delegate_(delegate),
      settings_(std::move(settings)),
      animator_(std::move(animator)),
      activity_running_(true),
      have_surface_(false),
      image_decoder_(task_runners,
                     vm.GetConcurrentWorkerTaskRunner(),
                     io_manager),
      task_runners_(std::move(task_runners)),
      weak_factory_(this) { 
 
  
  // Runtime controller is initialized here because it takes a reference to this
  // object as its delegate. The delegate may be called in the constructor and
  // we want to be fully initilazed by that point.
  runtime_controller_ = std::make_unique<RuntimeController>(
      *this,                        // runtime delegate
      &vm,                          // VM
      std::move(isolate_snapshot),  // isolate snapshot
      task_runners_,                // task runners
      std::move(snapshot_delegate),
      std::move(io_manager),                 // io manager
      std::move(unref_queue),                // Skia unref queue
      image_decoder_.GetWeakPtr(),           // image decoder
      settings_.advisory_script_uri,         // advisory script uri
      settings_.advisory_script_entrypoint,  // advisory script entrypoint
      settings_.idle_notification_callback,  // idle notification callback
      window_data,                           // window data
      settings_.isolate_create_callback,     // isolate create callback
      settings_.isolate_shutdown_callback,   // isolate shutdown callback
      settings_.persistent_isolate_data      // persistent isolate data
  );

  pointer_data_dispatcher_ = dispatcher_maker(*this);
}

Engine建立时,会马上建立一个RuntimeController,在RuntimeController中又会马上建立一个DartIsolate


2. 启动流程

启动流程从FLutterActivityonStart方法开始分析。

先看onStart方法代码:

// ./shell/platform/android/io/flutter/embedding/android/FlutterActivity.java
@Override
protected void onStart() { 
 
  
  super.onStart();
  lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START);
  delegate.onStart();
}

该方法先将生命周期调整为ON_START状态,而后调用FlutterActivityAndFragmentDelegateonStart方法。

下面是FlutterActivityAndFragmentDelegateonStart方法:

// ./shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java
void onStart() { 
 
  
  ensureAlive();
  doInitialFlutterViewRun();
}

这里先作了活动确认,后启动FlutterView内的Dart。

// ./shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java
private void doInitialFlutterViewRun() { 
 
  
  ...
  if (flutterEngine.getDartExecutor().isExecutingDart()) { 
 
  
    // No warning is logged because this situation will happen on every config
    // change if the developer does not choose to retain the Fragment instance.
    // So this is expected behavior in many cases.
    return;
  }
  ...
  // Configure the Dart entrypoint and execute it.
  DartExecutor.DartEntrypoint entrypoint =
      new DartExecutor.DartEntrypoint(
          host.getAppBundlePath(), host.getDartEntrypointFunctionName());
  flutterEngine.getDartExecutor().executeDartEntrypoint(entrypoint); // [9]
}

由于在指定的FlutterView中不支持重载或者重启Dart,因此须要先对DartExecutor判断是否正在执行代码。

  • [9] 以后经过从FlutterActivity中获取应用包路径和Dart入口方法,建立DartEntrypoint。根据这个DartEntrypoint执行Dart代码。

DartExecutorFlutterEngine建立的时候建立出来,并在dartExecutor.onAttachedToJNI方法中,将DartMessager设置到FlutterJNI中。

// ./shell/platform/android/io/flutter/embedding/engine/dart/DartExecutor.java
public void executeDartEntrypoint(@NonNull DartEntrypoint dartEntrypoint) { 
 
  
  ...
  flutterJNI.runBundleAndSnapshotFromLibrary(
      dartEntrypoint.pathToBundle, dartEntrypoint.dartEntrypointFunctionName, null, assetManager);
  ...
}

继续调用FlutterJNIrunBundleAndSnapshotFromLibrary方法。
FlutterJNI对线程和本地绑定确认后,调用native方法nativeRunBundleAndSnapshotFromLibrary。通过AndroidShellHolderLaunch调用后,最终会调用到ShellRunEngine方法。

下面看一下RunEngine方法:

// ./shell/common/shell.cc
void Shell::RunEngine(RunConfiguration run_configuration) { 
 
  
  RunEngine(std::move(run_configuration), nullptr);
}

void Shell::RunEngine(
    RunConfiguration run_configuration,
    const std::function<void(Engine::RunStatus)>& result_callback) { 
 
  
  // 此处传入的result_callback为空,后续在处理result时不作处理
  auto result = [platform_runner = task_runners_.GetPlatformTaskRunner(),
                 result_callback](Engine::RunStatus run_result) { 
 
  
    if (!result_callback) { 
 
  
      return;
    }
    platform_runner->PostTask(
        [result_callback, run_result]() { 
 
   result_callback(run_result); });
  };

  fml::TaskRunner::RunNowOrPostTask(
      task_runners_.GetUITaskRunner(), // [10]
      fml::MakeCopyable(
          [run_configuration = std::move(run_configuration),
           weak_engine = weak_engine_, result]() mutable { 
 
  
            ...
            auto run_result = weak_engine->Run(std::move(run_configuration));
            ...
            result(run_result);
          }));
}
  • [10] 前文中已经提到,Engine是建立、运行都在UI线程中的。因此此处Engine执行Dart代码须要在UI线程中执行。
// ./shell/common/engine.cc
Engine::RunStatus Engine::Run(RunConfiguration configuration) { 
 
  
  ...
  last_entry_point_ = configuration.GetEntrypoint();
  last_entry_point_library_ = configuration.GetEntrypointLibrary();
  auto isolate_launch_status =
      PrepareAndLaunchIsolate(std::move(configuration)); // [11]
  ...
  std::shared_ptr<DartIsolate> isolate =
      runtime_controller_->GetRootIsolate().lock();

  bool isolate_running =
      isolate && isolate->GetPhase() == DartIsolate::Phase::Running;

  if (isolate_running) { 
 
  
    ...
    std::string service_id = isolate->GetServiceId();
    fml::RefPtr<PlatformMessage> service_id_message =
        fml::MakeRefCounted<flutter::PlatformMessage>(
            kIsolateChannel, // 此处设置为IsolateChannel
            std::vector<uint8_t>(service_id.begin(), service_id.end()),
            nullptr);
    HandlePlatformMessage(service_id_message); // [12]
  }
  return isolate_running ? Engine::RunStatus::Success
                         : Engine::RunStatus::Failure;
}
  • [11] PrepareAndLaunchIsolate方法顾名思义,就是准备和启动Isolate,也便是在这个方法里进行了Dart运行。

  • [12] HandlePlatformMssage则是经过Flutter的消息机制,将DartIsolate的状态传递到Platform层进行处理。

继续查看PrepareAndLaunchIsolate方法:

// ./shell/common/engine.cc
Engine::RunStatus Engine::PrepareAndLaunchIsolate(
    RunConfiguration configuration) { 
 
  
  UpdateAssetManager(configuration.GetAssetManager());
  auto isolate_configuration = configuration.TakeIsolateConfiguration();
  std::shared_ptr<DartIsolate> isolate =
      runtime_controller_->GetRootIsolate().lock();
  ...
  if (!isolate_configuration->PrepareIsolate(*isolate)) { 
 
  
    return RunStatus::Failure;
  }
  if (configuration.GetEntrypointLibrary().empty()) { 
 
   // 以前传入的library为空,进入该分支
    if (!isolate->Run(configuration.GetEntrypoint(),
                      settings_.dart_entrypoint_args)) { 
 
  
      return RunStatus::Failure;
    }
  } else { 
 
  
    if (!isolate->RunFromLibrary(configuration.GetEntrypointLibrary(),
                                 configuration.GetEntrypoint(),
                                 settings_.dart_entrypoint_args)) { 
 
  
      return RunStatus::Failure;
    }
  }
}

在该方法中,通过对Isolate的一系列状态判断后,执行了Run方法:

// ./runtime/dart_isolate.cc
[[nodiscard]] bool DartIsolate::Run(const std::string& entrypoint_name,
                                    const std::vector<std::string>& args,
                                    const fml::closure& on_run) { 
 
  
  if (phase_ != Phase::Ready) { 
 
  
    return false;
  }

  tonic::DartState::Scope scope(this);

  auto user_entrypoint_function =
      Dart_GetField(Dart_RootLibrary(), tonic::ToDart(entrypoint_name.c_str()));

  auto entrypoint_args = tonic::ToDart(args);

  if (!InvokeMainEntrypoint(user_entrypoint_function, entrypoint_args)) { 
 
  
    return false;
  }

  phase_ = Phase::Running;

  if (on_run) { 
 
  
    on_run();
  }
  return true;
}

该方法将Isolate状态转换为Running,并调用主入口函数,即“main”方法。其中InvokeMainEntrypoint方法是真正执行Dart代码的地方。

// ./runtime/dart_isolate.cc
[[nodiscard]] static bool InvokeMainEntrypoint(
    Dart_Handle user_entrypoint_function,
    Dart_Handle args) { 
 
  
  ...
  Dart_Handle start_main_isolate_function =
      tonic::DartInvokeField(Dart_LookupLibrary(tonic::ToDart("dart:isolate")),
                             "_getStartMainIsolateFunction", { 
 
  });
  ...
  if (tonic::LogIfError(tonic::DartInvokeField(
          Dart_LookupLibrary(tonic::ToDart("dart:ui")), "_runMainZoned",
          { 
 
  start_main_isolate_function, user_entrypoint_function, args}))) { 
 
  
    return false;
  }
  return true;
}

到此,就完成了引擎的初始化和启动流程。


3. 总结

本篇文章主要分析了Flutter引擎的初始化和启动流程。
能够看出,在Flutter引擎中,Shell最重要的类,掌控对系统平台的适配和基本逻辑的控制。 在后续文章中,我会对Flutter的一些基本内容,如UI系统、消息机制、图形系统等等,进行详细分析。