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

相关推荐
我要最优解4 小时前
关于在mac中配置Java系统环境变量
java·flutter·macos
江上清风山间明月2 天前
Flutter开发的应用页面非常多时如何高效管理路由
android·flutter·路由·页面管理·routes·ongenerateroute
Zsnoin能2 天前
flutter国际化、主题配置、视频播放器UI、扫码功能、水波纹问题
flutter
早起的年轻人2 天前
Flutter CupertinoNavigationBar iOS 风格导航栏的组件
flutter·ios
HappyAcmen2 天前
关于Flutter前端面试题及其答案解析
前端·flutter
coooliang2 天前
Flutter 中的单例模式
javascript·flutter·单例模式
coooliang2 天前
Flutter项目中设置安卓启动页
android·flutter
JIngles1232 天前
flutter将utf-8编码的字节序列转换为中英文字符串
java·javascript·flutter
B.-3 天前
在 Flutter 中实现文件读写
开发语言·学习·flutter·android studio·xcode
freflying11193 天前
使用jenkins构建Android+Flutter项目依赖自动升级带来兼容性问题及Jenkins构建速度慢问题解决
android·flutter·jenkins