2023年6月28日发(作者:)
Flutter源码阅读分析:引擎初始化与启动引擎初始化与启动0. 前⾔Flutter是当前⽐较⽕热的前端开发框架,正好我最近也在做和Flutter引擎相关的⼯作,就顺⼿研究⼀下Flutter的源码。源码主要分为两部分:,是可供Flutter宿主应⽤提供的⼀个可移植运⾏时。Engine实现了Flutter的核⼼库,包括动画、图形、⽂件、⽹络I/O、访问⽀持、插件架构和Dart的运⾏时、编译⼯具链;,⼤部分的Flutter开发者主要通过Flutter Framework交互。Framework提供了⼀个现代的、可交互的框架,以及⼀个丰富的平台、布局、基础部件的集合。本⽂主要分析引擎的初始化流程和启动流程。1. 初始化流程1.1 Android平台适配层众所周知,Android应⽤的⼊⼝基本都是Activity,那么我们就先从Flutter的Activity开始着⼿分析。1.1.1 FlutterActivity在中存在两个FlutterActivity(和),其中在2020年5⽉13⽇的代码提交中,前⼀个FlutterActivity注释修改为废弃Activity基类。所以现在可⽤的Activity基类是后⼀个。根据的注释,我们可知:FlutterActivity是将Flutter集成到Android应⽤中的最简单最直接的⽅式,⽤于显⽰⼀个全屏的Flutter UI。主要职责是:显⽰⼀个Android的lauch screen;显⽰Flutter的splash screen;设置状态栏;选择Dart执⾏应⽤包路径和⼊⼝点;选择Flutter的初始化路由;如果需要的话,渲染透明度;提供⼦类钩⼦,提供和配置FlutterEngine。先从FlutterActivity定义看起:public class FlutterActivity extends Activity implements , LifecycleOwnerFlutterActivity继承于Activity。接⼝是在FlutterActivityAndFragmentDelegate中FlutterActivity持有类。Activity的onCreate⽅法是⼊⼝关键⽅法,看⼀下FlutterActivity的onCreate⽅法:// ./shell/platform/android/io/flutter/embedding/android/@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) { switchLaunchThemeForNormalTheme(); //
设置主题 te(savedInstanceState); LifecycleEvent(_CREATE); //
设置Android⽣命周期 delegate = new FlutterActivityAndFragmentDelegate(this); // [1] ch(this); vityCreated(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/nal class FlutterActivityAndFragmentDelegate { ... FlutterActivityAndFragmentDelegate(@NonNull Host 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( ivity(), nsparencyMode() == arent); ... flutterView = new FlutterView(ivity(), flutterSurfaceView); ... flutterSplashView = new FlutterSplashView(text()); ... yFlutterViewWithSplash(flutterView, eSplashScreen()); ToFlutterEngine(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 FlutterViewFlutterView的作⽤是将Flutter UI通过对应的FlutterEngine绘制后,显⽰在Android设备上。这⾥有两种渲染模式:surface和texture。在⼀般情况,我们都使⽤surface模式,即将Flutter UI绘制在SurfaceView上,这种模式拥有最优的性能,缺点是⽆法置于两个其他Android
View的z-index之间,同时也⽆法动画化或者进⾏变换。下⾯我们看⼀下FlutterView的源码实现:// ./shell/platform/android/io/flutter/embedding/android/blic class FlutterView extends FrameLayout { ... private FlutterView( @NonNull Context context, @Nullable AttributeSet attrs, @NonNull FlutterSurfaceView flutterSurfaceView) { super(context, attrs); rSurfaceView = flutterSurfaceView; Surface = 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) { ... rEngine = flutterEngine; // Instruct our FlutterRenderer that we are now its designated RenderSurface. FlutterRenderer flutterRenderer = derer(); ... ToRenderer(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(); tformViewsController().attachToView(this); // PlatformViewsController获取当前FlutterView ... }}[5] 将FlutterSurfaceView的Surface提供给指定的FlutterRender,⽤于将Flutter UI绘制到当前的FlutterSurfaceView。1.1.4 FlutterEngineFlutterEngine是⼀个独⽴的Flutter运⾏环境,是Dart代码运⾏在Android应⽤的容器。// ./shell/platform/android/io/flutter/embedding/engine//** Fully configurable {@code FlutterEngine} constructor. */
public FlutterEngine( @NonNull Context context, @NonNull FlutterLoader flutterLoader, @NonNull FlutterJNI flutterJNI, @NonNull PlatformViewsController platformViewsController, @Nullable String[] dartVmArgs, boolean automaticallyRegisterPlugins) { rJNI = flutterJNI; nitialization(licationContext()); ... attachToJni(); ecutor = new DartExecutor(flutterJNI, ets()); chedToJNI(); er = new FlutterRenderer(flutterJNI); ... xxxChannel = new XxxChannel(...); //
创建各个消息通道,⽤于传递事件、消息 ...}DartExecutor⽤于配置、启动、执⾏Dart代码,在后续分析中再详细研究。在FlutterActivityAndFragmentDelegate的setupFlutterEngine⽅法中调⽤的FlutterEngine构造⽅法没有传⼊FlutterJNI,在三参数构造⽅法中,会创建FlutterJNI对象,并传⼊全参数构造⽅法。FlutterJNI则是沟通Android的Java与Flutter引擎核⼼C++代码的桥梁。1.1.5 FlutterJNIFlutterJNI是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/blic 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 = nLooper(); } ... @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_ RegisterApi(JNIEnv* env) { static const JNINativeMethod flutter_jni_methods[] = { { .name = "nativeAttach", .signature = "(Lio/flutter/embedding/engine/FlutterJNI;Z)J", .fnPtr = reinterpret_cast(&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( // [6] FlutterMain::Get().GetSettings(), java_object, is_background_view); if (shell_holder->IsValid()) { return reinterpret_cast(shell_e()); } else { return 0; }}[6]
AndroidShellHolder是C/C++的Shell持有类。1.1.6 AndroidShellHolder在AndroidShellHolder中保存有Flutter设置参数、FlutterJNI的Java引⽤、PlatformViewAndroid对象(该对象在后续创建)、Shell对象等。// ./shell/platform/android/android_shell_oidShellHolder::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 weak_platform_view; Shell::CreateCallback on_create_platform_view = [is_background_view, java_object, &weak_platform_view](Shell& shell) { std::unique_ptr platform_view_android; ... platform_view_android = std::make_unique( // [7] shell, // delegate kRunners(), // task runners java_object, // java object handle for JNI interop tings() .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 ShellShell类是Flutter引擎中最重要的类之⼀。当嵌⼊应⽤创建了⼀个Flutter应⽤,都将创建⼀个Shell的实例,且嵌⼊者只持有⼀个Shell的unique指针。Shell是Flutter应⽤的“中枢神经系统”,包含了多个组件,并继承它们相应的Delegate类。下⾯看⼀下创建Shell的代码实现:// ./shell/common/::unique_ptr Shell::Create( TaskRunners task_runners, const WindowData window_data, Settings settings, Shell::CreateCallback on_create_platform_view, Shell::CreateCallback 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), // std::move(settings), // vm_data->GetIsolateSnapshot(), // isolate snapshot on_create_platform_view, // on_create_rasterizer, // std::move(vm) // );}std::unique_ptr Shell::Create( TaskRunners task_runners, const WindowData window_data, Settings settings, fml::RefPtr isolate_snapshot, const Shell::CreateCallback& on_create_platform_view, const Shell::CreateCallback& on_create_rasterizer, DartVMRef vm) { ... std::unique_ptr shell; fml::TaskRunner::RunNowOrPostTask( task_tformTaskRunner(), 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::CreateShellOnPlatformThread( DartVMRef vm, TaskRunners task_runners, const WindowData window_data, Settings settings, fml::RefPtr isolate_snapshot, const Shell::CreateCallback& on_create_platform_view, const Shell::CreateCallback& on_create_rasterizer) { ... auto shell = std::unique_ptr(new Shell(std::move(vm), task_runners, settings)); // Create the rasterizer on the raster thread. fml::TaskRunner::RunNowOrPostTask( task_terTaskRunner(), [&rasterizer_promise, // &snapshot_delegate_promise, on_create_rasterizer, // shell = () // ]() { std::unique_ptr rasterizer(on_create_rasterizer(*shell)); ... }); // Create the platform view on the platform thread (this thread). auto platform_view = on_create_platform_view(*()); ... // 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( platform_afe()->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 = (), // &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(*shell, task_runners, std::move(vsync_waiter)); engine__value(std::make_unique( *shell, // dispatcher_maker, // *shell->GetDartVM(), // std::move(isolate_snapshot), // task_runners, // window_data, // shell->GetSettings(), // std::move(animator), // weak_io_manager_(), // unref_queue_(), // snapshot_delegate_() // )); })); if (!shell->Setup(std::move(platform_view), // engine_(), // rasterizer_(), // io_manager_()) // ) { return nullptr; 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_ PlatformViewAndroid::NotifyCreated( fml::RefPtr 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_ PlatformView::NotifyCreated() { std::unique_ptr 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 RasterizerRasterizer是Shell的⼀个组成部分,运⾏在GPU线程中。每个Shell只能拥有⼀个Rasterizer实例。Rasterizer持有⼀个当前活动的在屏幕中显⽰的绘制Surface。Rasterizer在这个Surface上绘制从Engine中提交的layer tree。合成器上下⽂和屏上绘制Surface是Rasterizer的主要组成部分:合成器上下⽂包含绘制帧的所有必要的GPU状态。on_create_rasterizer⽅法在AndroidShellHolder的构造⽅法中给出:// ./shell/platform/android/android_shell_l::CreateCallback on_create_rasterizer = [](Shell& shell) { return std::make_unique(shell, kRunners());};// ./shell/common/erizer::Rasterizer(Delegate& delegate, TaskRunners task_runners) : Rasterizer(delegate, std::move(task_runners), std::make_unique( meBudget())) {}Rasterizer::Rasterizer( Delegate& delegate, TaskRunners task_runners, std::unique_ptr 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_s ShellIOManager final : public IOManager { ... void NotifyResourceContextAvailable(sk_sp resource_context); void UpdateResourceContext(sk_sp resource_context); ... fml::WeakPtr GetResourceContext() const override; fml::RefPtr GetSkiaUnrefQueue() const override;}ShellIOManager继承⾃IOManager类。IOManager是管理获取GrContext资源和Skia队列的⽅法的接⼝类。这两者都属于图形绘制相关内容,在后续⽂章中进⾏分析。NotifyResourceContextAvailable和UpdateResourceContext⽅法是通知GrContext创建和获取的⽅法。1.2.5 EngineEngine类是Shell的组成部分之⼀,运⾏于UI线程。其主要功能是管理根Isolate和它的运⾏时。每个Shell只能拥有⼀个Engine实例。Flutter应⽤的根Isolate会获取“窗⼝”绑定。通过这些绑定,⼀个⽤可以调度帧、推送layer tree⽤于渲染、请求解压图⽚并提交到GPU等等。Engine管理根Isolate的全部⽣命周期。当Engine被回收时,其持有者会认为根Isolate已经关闭且资源已经被回收。下⾯看⼀下Engine的构造⽅法:// ./shell/common/ne::Engine(Delegate& delegate, const PointerDataDispatcherMaker& dispatcher_maker, DartVM& vm, fml::RefPtr isolate_snapshot, TaskRunners task_runners, const WindowData window_data, Settings settings, std::unique_ptr animator, fml::WeakPtr io_manager, fml::RefPtr unref_queue, fml::WeakPtr snapshot_delegate) : delegate_(delegate), settings_(std::move(settings)), animator_(std::move(animator)), activity_running_(true), have_surface_(false), image_decoder_(task_runners, currentWorkerTaskRunner(), 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( *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/@Overrideprotected void onStart() { t(); LifecycleEvent(_START); t();}该⽅法先将⽣命周期调整为ON_START状态,然后调⽤FlutterActivityAndFragmentDelegate的onStart⽅法。下⾯是FlutterActivityAndFragmentDelegate的onStart⽅法:// ./shell/platform/android/io/flutter/embedding/android/id onStart() { ensureAlive(); doInitialFlutterViewRun();}这⾥先做了活动确认,后启动FlutterView内的Dart。// ./shell/platform/android/io/flutter/embedding/android/ivate void doInitialFlutterViewRun() { ... if (tExecutor().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. trypoint entrypoint = new trypoint( BundlePath(), tEntrypointFunctionName()); tExecutor().executeDartEntrypoint(entrypoint); // [9]}因为在指定的FlutterView中不⽀持重载或者重启Dart,所以需要先对DartExecutor判断是否正在执⾏代码。[9] 之后通过从FlutterActivity中获取应⽤包路径和Dart⼊⼝⽅法,创建DartEntrypoint。根据这个DartEntrypoint执⾏Dart代码。DartExecutor在FlutterEngine创建的时候创建出来,并在chedToJNI⽅法中,将DartMessager设置到FlutterJNI中。// ./shell/platform/android/io/flutter/embedding/engine/dart/blic void executeDartEntrypoint(@NonNull DartEntrypoint dartEntrypoint) { ... dleAndSnapshotFromLibrary( Bundle, trypointFunctionName, null, assetManager); ...}继续调⽤FlutterJNI的runBundleAndSnapshotFromLibrary⽅法。FlutterJNI对线程和本地绑定确认后,调⽤native⽅法nativeRunBundleAndSnapshotFromLibrary。经过AndroidShellHolder的Launch调⽤后,最终会调⽤到Shell的RunEngine⽅法。下⾯看⼀下RunEngine⽅法:// ./shell/common/ Shell::RunEngine(RunConfiguration run_configuration) { RunEngine(std::move(run_configuration), nullptr);}void Shell::RunEngine( RunConfiguration run_configuration, const std::function& 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/ne::RunStatus Engine::Run(RunConfiguration configuration) { ... last_entry_point_ = rypoint(); last_entry_point_library_ = rypointLibrary(); auto isolate_launch_status = PrepareAndLaunchIsolate(std::move(configuration)); // [11] ... std::shared_ptr 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 service_id_message = fml::MakeRefCounted( kIsolateChannel, //
此处设置为IsolateChannel std::vector(service_(), service_()), 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/ne::RunStatus Engine::PrepareAndLaunchIsolate( RunConfiguration configuration) { UpdateAssetManager(etManager()); auto isolate_configuration = olateConfiguration(); std::shared_ptr isolate = runtime_controller_->GetRootIsolate().lock(); ... if (!isolate_configuration->PrepareIsolate(*isolate)) { return RunStatus::Failure; } if (rypointLibrary().empty()) { //
之前传⼊的library为空,进⼊该分⽀ if (!isolate->Run(rypoint(), settings_.dart_entrypoint_args)) { return RunStatus::Failure; } } else { if (!isolate->RunFromLibrary(rypointLibrary(), rypoint(), settings_.dart_entrypoint_args)) { return RunStatus::Failure; } }}在该⽅法中,经过对Isolate的⼀系列状态判断后,执⾏了Run⽅法:// ./runtime/dart_[[nodiscard]] bool DartIsolate::Run(const std::string& entrypoint_name, const std::vector& 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_[[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系统、消息机制、图形系统等等,进⾏详细分析。
发布者:admin,转转请注明出处:http://www.yc00.com/news/1687955528a60619.html
评论列表(0条)