Flutter启动流程
简述
我们还是从Flutter在Android上启动流程来学习Flutter,只要学习了启动流程,就会对Flutter的实现有一些理解,否则像Flutter,RN这些对于原生应用开发者就像是一个黑盒子。
Flutter 在Android上必然还是要依赖于Activity的,Activity启动之后应该会启动dart虚拟机,执行dart上UI节点的构建,后续UI节点构建后应该会通过绘制引擎(skia,vulkan之类的)来渲染UI,本节主要来看第一个Activity启动dart虚拟机这个流程。
启动流程
我们根据官网来构建一个Flutter app,然后从Activity开始看。
1.1 MainActivity
这个MainActivity什么逻辑都没有,只是继承了FlutterActivity,这个FlutterActivity的源码在Flutter engine的仓库里。
我们来看一下Activity的onCreate和onStart里做的事~
class MainActivity: FlutterActivity()
1.2 FlutterActivity.onCreate
onCreate中构造了FlutterActivityAndFragmentDelegate,用于逻辑解耦,逻辑都在这个类里,然后调用onAttach,onAttach里构造了FlutterEngine,FlutterEngine里面包含了FlutterJNI,DartExecutor等,FlutterEngine核心逻辑都是C++写的,这里就是通过JNI绑定Native真实的实现。
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
// 配置主题
switchLaunchThemeForNormalTheme();
super.onCreate(savedInstanceState);
// 构建Delegate,逻辑解耦,主要的逻辑都在这个类里
delegate = new FlutterActivityAndFragmentDelegate(this);
// 构造绑定FlutterEngine
delegate.onAttach(this);
delegate.onRestoreInstanceState(savedInstanceState);
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
configureWindowForTransparency();
// 构造FlutterView,Flutter的渲染都在这个View上,详见1.3
setContentView(createFlutterView());
configureStatusBarForFullscreenFlutterExperience();
}
1.3 FlutterActivity.createFlutterView
调用了delegate的onCreateView构造FlutterView
private View createFlutterView() {
// 详见1.4
return delegate.onCreateView(
/* inflater=*/ null,
/* container=*/ null,
/* savedInstanceState=*/ null,
/*flutterViewId=*/ FLUTTER_VIEW_ID,
/*shouldDelayFirstAndroidViewDraw=*/ getRenderMode() == RenderMode.surface);
}
1.4 FlutterActivityAndFragmentDelegate.onCreateView
Android有两种渲染View,一种是基于TextureView的,一种是基于SurfaceView的,FlutterView继承了FrameLayout,然后会将这里的SurfaceView/TextureView添加到FlutterView中,后续的绘制都是在这个上面,我们来看SurfaceView的流程。
onCreate创建完FlutterView之后,我们接着看Activity onStart的流程。
View onCreateView(
LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState,
int flutterViewId,
boolean shouldDelayFirstAndroidViewDraw) {
Log.v(TAG, "Creating FlutterView.");
ensureAlive();
if (host.getRenderMode() == RenderMode.surface) {
FlutterSurfaceView flutterSurfaceView =
new FlutterSurfaceView(
host.getContext(), host.getTransparencyMode() == TransparencyMode.transparent);
// 这里什么也没做
host.onFlutterSurfaceViewCreated(flutterSurfaceView);
// 构建FlutterView
flutterView = new FlutterView(host.getContext(), flutterSurfaceView);
} else {
// 使用TextureView构建FlutterView
}
flutterView.addOnFirstFrameRenderedListener(flutterUiDisplayListener);
if (host.attachToEngineAutomatically()) {
Log.v(TAG, "Attaching FlutterEngine to FlutterView.");
flutterView.attachToFlutterEngine(flutterEngine);
}
flutterView.setId(flutterViewId);
if (shouldDelayFirstAndroidViewDraw) {
delayFirstAndroidViewDraw(flutterView);
}
return flutterView;
}
1.5 FlutterActivity.onStart
调用FlutterActivityAndFragmentDelegate.onStart
protected void onStart() {
super.onStart();
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START);
if (stillAttachedForEvent("onStart")) {
// 详见1.6
delegate.onStart();
}
}
1.6 FlutterActivityAndFragmentDelegate.onStart
调用doInitialFlutterViewRun来初始化Flutter实现的View
void onStart() {
Log.v(TAG, "onStart()");
ensureAlive();
// 初始化View的流程。详见1.7
doInitialFlutterViewRun();
if (previousVisibility != null) {
flutterView.setVisibility(previousVisibility);
}
}
1.7 FlutterActivityAndFragmentDelegate.doInitialFlutterViewRun
根据配置寻找dart入口点,主要是dart的文件路径和入口函数。
然后将入口信息封装到DartEntrypoint,调用executeDartEntrypoint执行dart。
private void doInitialFlutterViewRun() {
// 检查是否有缓存
if (host.getCachedEngineId() != null) {
return;
}
if (flutterEngine.getDartExecutor().isExecutingDart()) {
return;
}
// 这里根据配置寻找dart的入口点根目录
String initialRoute = host.getInitialRoute();
if (initialRoute == null) {
initialRoute = maybeGetInitialRouteFromIntent(host.getActivity().getIntent());
if (initialRoute == null) {
initialRoute = DEFAULT_INITIAL_ROUTE;
}
}
@Nullable String libraryUri = host.getDartEntrypointLibraryUri();
flutterEngine.getNavigationChannel().setInitialRoute(initialRoute);
String appBundlePathOverride = host.getAppBundlePath();
if (appBundlePathOverride == null || appBundlePathOverride.isEmpty()) {
appBundlePathOverride = FlutterInjector.instance().flutterLoader().findAppBundlePath();
}
// 构建DartEntrypoint,这个封装了入口点信息,主要是dart入口的文件路径和入口函数
DartExecutor.DartEntrypoint entrypoint =
libraryUri == null
? new DartExecutor.DartEntrypoint(
appBundlePathOverride, host.getDartEntrypointFunctionName())
: new DartExecutor.DartEntrypoint(
appBundlePathOverride, libraryUri, host.getDartEntrypointFunctionName());
// 执行dart入口函数,详见1.8
flutterEngine.getDartExecutor().executeDartEntrypoint(entrypoint, host.getDartEntrypointArgs());
}
1.8 executeDartEntrypoint
调用flutterJNI.runBundleAndSnapshotFromLibrary执行dart入口函数。
public void executeDartEntrypoint(
@NonNull DartEntrypoint dartEntrypoint, @Nullable List<String> dartEntrypointArgs) {
// 如果已经执行过dart虚拟机,就返回
if (isApplicationRunning) {
Log.w(TAG, "Attempted to run a DartExecutor that is already running.");
return;
}
try (TraceSection e = TraceSection.scoped("DartExecutor#executeDartEntrypoint")) {
Log.v(TAG, "Executing Dart entrypoint: " + dartEntrypoint);
// 调用flutterJNI.runBundleAndSnapshotFromLibrary执行dart,详见1.9
flutterJNI.runBundleAndSnapshotFromLibrary(
dartEntrypoint.pathToBundle,
dartEntrypoint.dartEntrypointFunctionName,
dartEntrypoint.dartEntrypointLibrary,
assetManager,
dartEntrypointArgs);
isApplicationRunning = true;
}
}
1.9 FlutterJNI.runBundleAndSnapshotFromLibrary
调用native函数,到C++层。
public void runBundleAndSnapshotFromLibrary(
@NonNull String bundlePath,
@Nullable String entrypointFunctionName,
@Nullable String pathToEntrypointFunction,
@NonNull AssetManager assetManager,
@Nullable List<String> entrypointArgs) {
ensureRunningOnMainThread();
ensureAttachedToNative();
// 详见1.10
nativeRunBundleAndSnapshotFromLibrary(
nativeShellHolderId,
bundlePath,
entrypointFunctionName,
pathToEntrypointFunction,
assetManager,
entrypointArgs);
}
1.10 RunBundleAndSnapshotFromLibrary
jni调用到C++层。
static void RunBundleAndSnapshotFromLibrary(JNIEnv* env,
jobject jcaller,
jlong shell_holder,
jstring jBundlePath,
jstring jEntrypoint,
jstring jLibraryUrl,
jobject jAssetManager,
jobject jEntrypointArgs) {
auto apk_asset_provider = std::make_unique<flutter::APKAssetProvider>(
env, // jni environment
jAssetManager, // asset manager
fml::jni::JavaStringToString(env, jBundlePath) // apk asset dir
);
auto entrypoint = fml::jni::JavaStringToString(env, jEntrypoint);
auto libraryUrl = fml::jni::JavaStringToString(env, jLibraryUrl);
auto entrypoint_args = fml::jni::StringListToVector(env, jEntrypointArgs);
// 详见1.11
ANDROID_SHELL_HOLDER->Launch(std::move(apk_asset_provider), entrypoint,
libraryUrl, entrypoint_args);
}
1.11 AndroidShellHolder::Launch
将dart入口函数信息封装到BuildRunConfiguration,然后调用RunEngine来执行。
void AndroidShellHolder::Launch(
std::unique_ptr<APKAssetProvider> apk_asset_provider,
const std::string& entrypoint,
const std::string& libraryUrl,
const std::vector<std::string>& entrypoint_args) {
if (!IsValid()) {
return;
}
apk_asset_provider_ = std::move(apk_asset_provider);
// 封装入口信息到BuildRunConfiguration
auto config = BuildRunConfiguration(entrypoint, libraryUrl, entrypoint_args);
if (!config) {
return;
}
UpdateDisplayMetrics();
// 详见1.12
shell_->RunEngine(std::move(config.value()));
}
1.12 Shell::RunEngine
通过engine->Run调用dart代码,这里RunEngine我们省略了一个重载函数,就是result_callback为null。
result_callback是用于dart执行完成之后回调使用的。
void Shell::RunEngine(
RunConfiguration run_configuration,
const std::function<void(Engine::RunStatus)>& result_callback) {
// 这里result_callback是null,我们省略了一个重载函数,result_callback是用于调用执行完dart之后回调的方法。
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_DCHECK(is_set_up_);
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetUITaskRunner(),
fml::MakeCopyable(
[run_configuration = std::move(run_configuration),
weak_engine = weak_engine_, result]() mutable {
// weak_engine是flutter的engine,如果这里没拿到就直接返回失败
if (!weak_engine) {
FML_LOG(ERROR)
<< "Could not launch engine with configuration - no engine.";
result(Engine::RunStatus::Failure);
return;
}
// 通过engine->Run执行dart代码,详见1.13
auto run_result = weak_engine->Run(std::move(run_configuration));
if (run_result == flutter::Engine::RunStatus::Failure) {
FML_LOG(ERROR) << "Could not launch engine with configuration.";
}
result(run_result);
}));
}
1.13 Engine::Run
调用runtime_controller_->LaunchRootIsolate
Engine::RunStatus Engine::Run(RunConfiguration configuration) {
// ...
last_entry_point_ = configuration.GetEntrypoint();
last_entry_point_library_ = configuration.GetEntrypointLibrary();
// ...
UpdateAssetManager(configuration.GetAssetManager());
if (runtime_controller_->IsRootIsolateRunning()) {
return RunStatus::FailureAlreadyRunning;
}
auto root_isolate_create_callback = [&]() {
if (settings_.prefetched_default_font_manager) {
SetupDefaultFontManager();
}
};
// 调用runtime_controller_的LaunchRootIsolate执行dart逻辑,详见1.14
if (!runtime_controller_->LaunchRootIsolate(
settings_, //
root_isolate_create_callback, //
configuration.GetEntrypoint(), //
configuration.GetEntrypointLibrary(), //
configuration.GetEntrypointArgs(), //
configuration.TakeIsolateConfiguration()) //
) {
return RunStatus::Failure;
}
// ...
return Engine::RunStatus::Success;
}
1.14 RuntimeController::LaunchRootIsolate
调用DartIsolate::CreateRunningRootIsolate执行dart虚拟机
bool RuntimeController::LaunchRootIsolate(
const Settings& settings,
const fml::closure& root_isolate_create_callback,
std::optional<std::string> dart_entrypoint,
std::optional<std::string> dart_entrypoint_library,
const std::vector<std::string>& dart_entrypoint_args,
std::unique_ptr<IsolateConfiguration> isolate_configuration) {
// ...通过锁检查是否已经构建了DartIsolate
// 调用CreateRunningRootIsolate,详见1.15
auto strong_root_isolate =
DartIsolate::CreateRunningRootIsolate(
settings, //
isolate_snapshot_, //
std::make_unique<PlatformConfiguration>(this), //
DartIsolate::Flags{}, //
root_isolate_create_callback, //
isolate_create_callback_, //
isolate_shutdown_callback_, //
std::move(dart_entrypoint), //
std::move(dart_entrypoint_library), //
dart_entrypoint_args, //
std::move(isolate_configuration), //
context_, //
spawning_isolate_.lock().get()) //
.lock();
if (!strong_root_isolate) {
FML_LOG(ERROR) << "Could not create root isolate.";
return false;
}
strong_root_isolate->GetIsolateGroupData().SetPlatformMessageHandler(
strong_root_isolate->GetRootIsolateToken(),
client_.GetPlatformMessageHandler());
root_isolate_ = strong_root_isolate;
strong_root_isolate->SetReturnCodeCallback(
[this](uint32_t code) { root_isolate_return_code_ = code; });
// ...
return true;
}
1.15 DartIsolate::CreateRunningRootIsolate
做了一些检查后,处理和配置了dart虚拟机创建和销毁回调,然后调用RunFromLibrary执行dart。
std::weak_ptr<DartIsolate> DartIsolate::CreateRunningRootIsolate(
const Settings& settings,
const fml::RefPtr<const DartSnapshot>& isolate_snapshot,
std::unique_ptr<PlatformConfiguration> platform_configuration,
Flags isolate_flags,
const fml::closure& root_isolate_create_callback,
const fml::closure& isolate_create_callback,
const fml::closure& isolate_shutdown_callback,
std::optional<std::string> dart_entrypoint,
std::optional<std::string> dart_entrypoint_library,
const std::vector<std::string>& dart_entrypoint_args,
std::unique_ptr<IsolateConfiguration> isolate_configuration,
const UIDartState::Context& context,
const DartIsolate* spawning_isolate) {
// ...
isolate_flags.SetNullSafetyEnabled(
isolate_configuration->IsNullSafetyEnabled(*isolate_snapshot));
isolate_flags.SetIsDontNeedSafe(isolate_snapshot->IsDontNeedSafe());
auto isolate = CreateRootIsolate(settings, //
isolate_snapshot, //
std::move(platform_configuration), //
isolate_flags, //
isolate_create_callback, //
isolate_shutdown_callback, //
context, //
spawning_isolate //
)
.lock();
// ...
// 回调dart虚拟机创建的回调
if (settings.root_isolate_create_callback) {
tonic::DartState::Scope scope(isolate.get());
settings.root_isolate_create_callback(*isolate.get());
}
if (root_isolate_create_callback) {
root_isolate_create_callback();
}
// 调用RunFromLibrary执行dart,详见1.16
if (!isolate->RunFromLibrary(std::move(dart_entrypoint_library), //
std::move(dart_entrypoint), //
dart_entrypoint_args)) {
FML_LOG(ERROR) << "Could not run the run main Dart entrypoint.";
return {};
}
// 配置dart虚拟机shutdown回调
if (settings.root_isolate_shutdown_callback) {
isolate->AddIsolateShutdownCallback(
settings.root_isolate_shutdown_callback);
}
shutdown_on_error.Release();
return isolate;
}
1.16 DartIsolate::RunFromLibrary
获取dart入口函数,使用Dart_GetField获取入口函数,调用InvokeMainEntrypoint执行dart虚拟机。
bool DartIsolate::RunFromLibrary(std::optional<std::string> library_name,
std::optional<std::string> entrypoint,
const std::vector<std::string>& args) {
TRACE_EVENT0("flutter", "DartIsolate::RunFromLibrary");
if (phase_ != Phase::Ready) {
return false;
}
tonic::DartState::Scope scope(this);
// 获取dart入口库信息
auto library_handle =
library_name.has_value() && !library_name.value().empty()
? ::Dart_LookupLibrary(tonic::ToDart(library_name.value().c_str()))
: ::Dart_RootLibrary();
// 获取dart的入口点
auto entrypoint_handle = entrypoint.has_value() && !entrypoint.value().empty()
? tonic::ToDart(entrypoint.value().c_str())
: tonic::ToDart("main");
if (!FindAndInvokeDartPluginRegistrant()) {
InvokeDartPluginRegistrantIfAvailable(library_handle);
}
// 获取dart入口函数
auto user_entrypoint_function =
::Dart_GetField(library_handle, entrypoint_handle);
auto entrypoint_args = tonic::ToDart(args);
// 调用dart虚拟机,详见1.17
if (!InvokeMainEntrypoint(user_entrypoint_function, entrypoint_args)) {
return false;
}
phase_ = Phase::Running;
return true;
}
1.17 InvokeMainEntrypoint
调用DartInvokeField来调用Dart的方法,Dart_LookupLibrary和DartInvokeField都是dart sdk提供的接口。
这里之后就到了main.dart进入dart入口。
[[nodiscard]] static bool InvokeMainEntrypoint(
Dart_Handle user_entrypoint_function,
Dart_Handle args) {
// ...
// 调用DartInvokeField
Dart_Handle start_main_isolate_function =
tonic::DartInvokeField(Dart_LookupLibrary(tonic::ToDart("dart:isolate")),
"_getStartMainIsolateFunction", {});
if (tonic::CheckAndHandleError(start_main_isolate_function)) {
FML_LOG(ERROR) << "Could not resolve main entrypoint trampoline.";
return false;
}
if (tonic::CheckAndHandleError(tonic::DartInvokeField(
Dart_LookupLibrary(tonic::ToDart("dart:ui")), "_runMain",
{start_main_isolate_function, user_entrypoint_function, args}))) {
FML_LOG(ERROR) << "Could not invoke the main entrypoint.";
return false;
}
return true;
}
小结
我们基于Flutter在Android上的启动流程,来了解了一下Flutter app是怎么构建构建FlutterView,启动dart虚拟机,然后进入dart入口的。
后面我们会介绍dart层是怎么管理Widget,然后进行渲染的。