Flutter启动流程(2)

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,然后进行渲染的。

相关推荐
0wioiw01 小时前
Flutter基础(FFI)
flutter
Georgewu9 天前
【HarmonyOS 5】鸿蒙跨平台开发方案详解(一)
flutter·harmonyos
爱吃鱼的锅包肉9 天前
Flutter开发中记录一个非常好用的图片缓存清理的插件
flutter
张风捷特烈10 天前
每日一题 Flutter#13 | build 回调的 BuildContext 是什么
android·flutter·面试
恋猫de小郭10 天前
Flutter 又双叒叕可以在 iOS 26 的真机上 hotload 运行了,来看看又是什么黑科技
android·前端·flutter
QC七哥10 天前
跨平台开发flutter初体验
android·flutter·安卓·桌面开发
小喷友10 天前
Flutter 从入门到精通(水)
前端·flutter·app
恋猫de小郭11 天前
Flutter 里的像素对齐问题,深入理解为什么界面有时候会出现诡异的细线?
android·前端·flutter
tbit11 天前
dart私有命名构造函数的作用与使用场景
flutter·dart