引擎初始化与启动
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/flutter
本文主要分析引擎的初始化流程和启动流程。
1. 初始化流程
1.1 Android平台适配层
众所周知,Android应用的入口基本都是Activity,那么我们就先从Flutter的Activity开始着手分析。
1.1.1 FlutterActivity
在Engine中存在两个FlutterActivity(shell/platform/android/io/flutter/app/FlutterActivity.java和shell/platform/android/io/flutter/embedding/android/FlutterActivity.java),其中在2020年5月13日的代码提交中,前一个FlutterActivity注释修改为废弃Activity基类。所以现在可用的Activity基类是后一个。
根据FlutterActivity的注释,我们可知:
FlutterActivity
是将Flutter集成到Android应用中的最简单最直接的方式,用于显示一个全屏的Flutter UI。主要职责是:
- 显示一个Android的lauch screen;
- 显示Flutter的splash screen;
- 设置状态栏;
- 选择Dart执行应用包路径和入口点;
- 选择Flutter的初始化路由;
- 如果需要的话,渲染透明度;
- 提供子类钩子,提供和配置FlutterEngine。
先从FlutterActivity
定义看起:
public class FlutterActivity extends Activity
implements FlutterActivityAndFragmentDelegate.Host, LifecycleOwner
FlutterActivity
继承于Activity
。FlutterActivityAndFragmentDelegate.Host
接口是在FlutterActivityAndFragmentDelegate
中FlutterActivity
持有类。
Activity
的onCreate
方法是入口关键方法,看一下FlutterActivity
的onCreate
方法:
// ./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
类实现了FlutterActivity
与FlutterFragment
之间相同的逻辑。 - [2] 通过调用
FlutterActivityAndFragmentDelegate
的onCreateView
方法创建出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. 通过Host
的configureFlutterEngine
方法配置FlutterEngine
。 - [4] 'onCreateView’方法主要做以下事情:1. 在View树中创建一个新的
FlutterView
;2. 在FlutterView
中添加一个FlutterUiDisplayListener
;3. 将FlutterEngine
附着到FlutterView
上;4. 返回这个新的View树。
在这里出现了两个比较重要的类,FlutterView
和FlutterEngine
。
1.1.3 FlutterView
FlutterView
的作用是将Flutter UI通过对应的FlutterEngine
绘制后,显示在Android设备上。这里有两种渲染模式:surface
和texture
。
在一般情况,我们都使用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] 将
FlutterSurfaceView
的Surface
提供给指定的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代码,在后续分析中再详细研究。
在FlutterActivityAndFragmentDelegate
的setupFlutterEngine
方法中调用的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
主要起到一个沟通Surface
和Shell
的作用。
1.2.3 Rasterizer
Rasterizer
是Shell
的一个组成部分,运行在GPU线程中。每个Shell
只能拥有一个Rasterizer
实例。Rasterizer
持有一个当前活动的在屏幕中显示的绘制Surface
。Rasterizer
在这个Surface
上绘制从Engine
中提交的layer tree。合成器上下文和屏上绘制Surface
是Rasterizer
的主要组成部分:合成器上下文包含绘制帧的所有必要的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队列的方法的接口类。这两者都属于图形绘制相关内容,在后续文章中进行分析。
NotifyResourceContextAvailable
和UpdateResourceContext
方法是通知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. 启动流程
启动流程从FLutterActivity
的onStart
方法开始分析。
先看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
状态,然后调用FlutterActivityAndFragmentDelegate
的onStart
方法。
下面是FlutterActivityAndFragmentDelegate
的onStart
方法:
// ./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代码。
DartExecutor
在FlutterEngine
创建的时候创建出来,并在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);
...
}
继续调用FlutterJNI
的runBundleAndSnapshotFromLibrary
方法。
FlutterJNI
对线程和本地绑定确认后,调用native方法nativeRunBundleAndSnapshotFromLibrary
。经过AndroidShellHolder
的Launch
调用后,最终会调用到Shell
的RunEngine
方法。
下面看一下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系统、消息机制、图形系统等等,进行详细分析。