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

相关推荐
m0_748247801 小时前
Flutter Intl包使用指南:实现国际化和本地化
前端·javascript·flutter
迷雾漫步者3 小时前
Flutter组件————PageView
flutter·跨平台·dart
迷雾漫步者10 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
coder_pig15 小时前
📝小记:Ubuntu 部署 Jenkins 打包 Flutter APK
flutter·ubuntu·jenkins
捡芝麻丢西瓜17 小时前
flutter自学笔记5- dart 编码规范
flutter·dart
恋猫de小郭17 小时前
什么?Flutter 可能会被 SwiftUI/ArkUI 化?全新的 Flutter Roadmap
flutter·ios·swiftui
sunly_2 天前
Flutter:导航,tab切换,顶部固定,列表分页滚动
开发语言·javascript·flutter
敲代码的小强2 天前
Flutter项目兼容鸿蒙Next系统
flutter·华为·harmonyos
Zh-jie2 天前
flutter 快速实现侧边栏
前端·javascript·flutter
truemi.733 天前
flutter --no-color pub get 超时解决方法
android·flutter