Flutter是当前比较火热的前端开发框架,正好我最近也在作和Flutter引擎相关的工做,就顺手研究一下Flutter的源码。
源码主要分为两部分:前端
Flutter官方源码下载路径:
engine: https://github.com/flutter/engine
flutter framework: https://github.com/flutter/flutterjava
本文主要分析引擎的初始化流程和启动流程。android
众所周知,Android应用的入口基本都是Activity,那么咱们就先从Flutter的Activity开始着手分析。git
在Engine中存在两个FlutterActivity(shell/platform/android/io/flutter/app/FlutterActivity.java和shell/platform/android/io/flutter/embedding/android/FlutterActivity.java),其中在2020年5月13日的代码提交中,前一个FlutterActivity注释修改成废弃Activity基类。因此如今可用的Activity基类是后一个。
根据FlutterActivity的注释,咱们可知:
FlutterActivity
是将Flutter集成到Android应用中的最简单最直接的方式,用于显示一个全屏的Flutter UI。主要职责是:github
先从FlutterActivity
定义看起:web
public class FlutterActivity extends Activity implements FlutterActivityAndFragmentDelegate.Host, LifecycleOwner
FlutterActivity
继承于Activity
。FlutterActivityAndFragmentDelegate.Host
接口是在FlutterActivityAndFragmentDelegate
中FlutterActivity
持有类。shell
Activity
的onCreate
方法是入口关键方法,看一下FlutterActivity
的onCreate
方法:promise
// ./shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @Override protected void onCreate(@Nullable Bundle savedInstanceState) { switchLaunchThemeForNormalTheme(); // 设置主题 super.onCreate(savedInstanceState); lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE); // 设置Android生命周期 delegate = new FlutterActivityAndFragmentDelegate(this); // [1] delegate.onAttach(this); delegate.onActivityCreated(savedInstanceState); configureWindowForTransparency(); // 设置背景透明模式 setContentView(createFlutterView()); // [2] configureStatusBarForFullscreenFlutterExperience(); // 配置系统状态栏 }
FlutterActivityAndFragmentDelegate
类实现了FlutterActivity
与FlutterFragment
之间相同的逻辑。FlutterActivityAndFragmentDelegate
的onCreateView
方法建立出FlutterView
并将其添加到界面上。FlutterView
用于在Android设备上显示Flutter UI。下面就再分析一下FlutterActivityAndFragmentDelegate
的源码逻辑:网络
// ./shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java final class FlutterActivityAndFragmentDelegate { ... FlutterActivityAndFragmentDelegate(@NonNull Host host) { this.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( host.getActivity(), host.getTransparencyMode() == TransparencyMode.transparent); ... flutterView = new FlutterView(host.getActivity(), flutterSurfaceView); ... flutterSplashView = new FlutterSplashView(host.getContext()); ... flutterSplashView.displayFlutterViewWithSplash(flutterView, host.provideSplashScreen()); flutterView.attachToFlutterEngine(flutterEngine); return } ... return flutterSplashView; }
onAttach
方法主要作了如下事情:1. 初始化Flutter系统;2. 获取或者建立一个FlutterEngine
;3. 建立和配置PlatformPlugin
;4. 将FlutterEngine
附在Activity
上;5. 经过Host
的configureFlutterEngine
方法配置FlutterEngine
。FlutterView
;2. 在FlutterView
中添加一个FlutterUiDisplayListener
;3. 将FlutterEngine
附着到FlutterView
上;4. 返回这个新的View树。在这里出现了两个比较重要的类,FlutterView
和FlutterEngine
。架构
FlutterView
的做用是将Flutter UI经过对应的FlutterEngine
绘制后,显示在Android设备上。这里有两种渲染模式:surface
和texture
。
在通常状况,咱们都使用surface
模式,即将Flutter UI绘制在SurfaceView
上,这种模式拥有最优的性能,缺点是没法置于两个其余Android View
的z-index之间,同时也没法动画化或者进行变换。
下面咱们看一下FlutterView
的源码实现:
// ./shell/platform/android/io/flutter/embedding/android/FlutterView.java public class FlutterView extends FrameLayout { ... private FlutterView( @NonNull Context context, @Nullable AttributeSet attrs, @NonNull FlutterSurfaceView flutterSurfaceView) { super(context, attrs); this.flutterSurfaceView = flutterSurfaceView; this.renderSurface = 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) { ... this.flutterEngine = flutterEngine; // Instruct our FlutterRenderer that we are now its designated RenderSurface. FlutterRenderer flutterRenderer = this.flutterEngine.getRenderer(); ... renderSurface.attachToRenderer(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(); flutterEngine.getPlatformViewsController().attachToView(this); // PlatformViewsController获取当前FlutterView ... } }
FlutterSurfaceView
的Surface
提供给指定的FlutterRender
,用于将Flutter UI绘制到当前的FlutterSurfaceView
。FlutterEngine
是一个独立的Flutter运行环境,是Dart代码运行在Android应用的容器。
// ./shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java /** Fully configurable {@code FlutterEngine} constructor. */ public FlutterEngine( @NonNull Context context, @NonNull FlutterLoader flutterLoader, @NonNull FlutterJNI flutterJNI, @NonNull PlatformViewsController platformViewsController, @Nullable String[] dartVmArgs, boolean automaticallyRegisterPlugins) { this.flutterJNI = flutterJNI; flutterLoader.startInitialization(context.getApplicationContext()); ... attachToJni(); this.dartExecutor = new DartExecutor(flutterJNI, context.getAssets()); this.dartExecutor.onAttachedToJNI(); this.renderer = new FlutterRenderer(flutterJNI); ... xxxChannel = new XxxChannel(...); // 建立各个消息通道,用于传递事件、消息 ... }
DartExecutor
用于配置、启动、执行Dart代码,在后续分析中再详细研究。
在FlutterActivityAndFragmentDelegate
的setupFlutterEngine
方法中调用的FlutterEngine
构造方法没有传入FlutterJNI
,在三参数构造方法中,会建立FlutterJNI
对象,并传入全参数构造方法。FlutterJNI
则是沟通Android的Java与Flutter引擎核心C++代码的桥梁。
FlutterJNI
是Flutter内嵌Java代码和引擎C++代码之间的接口。
Flutter引擎的代码是使用C++实现的。Android Flutter嵌入则负责协调Android系统事件和应用用户交互事件。这些事件协调须要消息交流接口,这就须要用到JNI(Java Native Interface)来穿过Java/native边界。
在Flutter的设计中,全部的JNI接口都集中在FlutterJNI
这个类中。这么作主要有如下几个缘由:
大部分FlutterJNI
中的调用都与特定的“platform view”相关,而“platform view”的数量可能会不少。因此,在执行了attachToNative
方法后,每一个FlutterJNI
实例都持有一个本地“platform view”的ID,且这个ID与bendingC/C++引擎代码共享。这个ID会被传递到全部的具体platform view的本地方法。
// ./shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java public 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 = Looper.getMainLooper(); } ... @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_jni.cc bool RegisterApi(JNIEnv* env) { static const JNINativeMethod flutter_jni_methods[] = { { .name = "nativeAttach", .signature = "(Lio/flutter/embedding/engine/FlutterJNI;Z)J", .fnPtr = reinterpret_cast<void*>(&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<AndroidShellHolder>( // [6] FlutterMain::Get().GetSettings(), java_object, is_background_view); if (shell_holder->IsValid()) { return reinterpret_cast<jlong>(shell_holder.release()); } else { return 0; } }
AndroidShellHolder
是C/C++的Shell
持有类。在AndroidShellHolder
中保存有Flutter设置参数、FlutterJNI的Java引用、PlatformViewAndroid
对象(该对象在后续建立)、Shell
对象等。
// ./shell/platform/android/android_shell_holder.cc AndroidShellHolder::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<PlatformViewAndroid> weak_platform_view; Shell::CreateCallback<PlatformView> on_create_platform_view = [is_background_view, java_object, &weak_platform_view](Shell& shell) { std::unique_ptr<PlatformViewAndroid> platform_view_android; ... platform_view_android = std::make_unique<PlatformViewAndroid>( // [7] shell, // delegate shell.GetTaskRunners(), // task runners java_object, // java object handle for JNI interop shell.GetSettings() .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; ... }
PlatformViewAndroid
,该类继承于PlatformView
。各平台会根据自身特色继承PlatformView
类,实现自身平台的PlatformView
。Shell
对象,该类是Flutter引擎的关键类,此后的代码将于平台无关,为各个平台的通用代码。Shell
类是Flutter引擎中最重要的类之一。当嵌入应用建立了一个Flutter应用,都将建立一个Shell
的实例,且嵌入者只持有一个Shell
的unique指针。
Shell
是Flutter应用的“中枢神经系统”,包含了多个组件,并继承它们相应的Delegate
类。
下面看一下建立Shell
的代码实现:
// ./shell/common/shell.cc std::unique_ptr<Shell> Shell::Create( TaskRunners task_runners, const WindowData window_data, Settings settings, Shell::CreateCallback<PlatformView> on_create_platform_view, Shell::CreateCallback<Rasterizer> 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), // vm_data->GetIsolateSnapshot(), // isolate snapshot on_create_platform_view, // on_create_rasterizer, // std::move(vm) // ); } std::unique_ptr<Shell> Shell::Create( TaskRunners task_runners, const WindowData window_data, Settings settings, fml::RefPtr<const DartSnapshot> isolate_snapshot, const Shell::CreateCallback<PlatformView>& on_create_platform_view, const Shell::CreateCallback<Rasterizer>& on_create_rasterizer, DartVMRef vm) { ... std::unique_ptr<Shell> shell; fml::TaskRunner::RunNowOrPostTask( task_runners.GetPlatformTaskRunner(), 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> Shell::CreateShellOnPlatformThread( DartVMRef vm, TaskRunners task_runners, const WindowData window_data, Settings settings, fml::RefPtr<const DartSnapshot> isolate_snapshot, const Shell::CreateCallback<PlatformView>& on_create_platform_view, const Shell::CreateCallback<Rasterizer>& on_create_rasterizer) { ... auto shell = std::unique_ptr<Shell>(new Shell(std::move(vm), task_runners, settings)); // Create the rasterizer on the raster thread. fml::TaskRunner::RunNowOrPostTask( task_runners.GetRasterTaskRunner(), [&rasterizer_promise, // &snapshot_delegate_promise, on_create_rasterizer, // shell = shell.get() // ]() { std::unique_ptr<Rasterizer> rasterizer(on_create_rasterizer(*shell)); ... }); // Create the platform view on the platform thread (this thread). auto platform_view = on_create_platform_view(*shell.get()); ... // 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<ShellIOManager>( platform_view.getUnsafe()->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 = shell.get(), // &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<Animator>(*shell, task_runners, std::move(vsync_waiter)); engine_promise.set_value(std::make_unique<Engine>( *shell, // dispatcher_maker, // *shell->GetDartVM(), // std::move(isolate_snapshot), // task_runners, // window_data, // shell->GetSettings(), // std::move(animator), // weak_io_manager_future.get(), // unref_queue_future.get(), // snapshot_delegate_future.get() // )); })); if (!shell->Setup(std::move(platform_view), // engine_future.get(), // rasterizer_future.get(), // io_manager_future.get()) // ) { return nullptr; } return shell; }
从代码中能够看出,在platform线程中建立了Shell
,以后分别在栅格化线程中建立Rasterizer
,在platform线程中建立PlatformView
,在IO线程中建立ShellIOManager
,在UI线程中建立Engine
,并将这四者设置到Shell
中去。
Shell
分别继承了四者的Delegate
,四者经过相应的Delegate
将事件传递到Shell
。
下面分别看一下这四个类。
在Android平台中,真正实现的是PlarformViewAndroid
类,主要方法实现的功能都是在栅格化线程中对AndroidSurface
进行操做。看一下NotifyCreated
方法的实现:
// ./shell/platform/android/platform_view_android.cc void PlatformViewAndroid::NotifyCreated( fml::RefPtr<AndroidNativeWindow> 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_view.cc void PlatformView::NotifyCreated() { std::unique_ptr<Surface> 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
的做用。
Rasterizer
是Shell
的一个组成部分,运行在GPU线程中。每一个Shell
只能拥有一个Rasterizer
实例。Rasterizer
持有一个当前活动的在屏幕中显示的绘制Surface
。Rasterizer
在这个Surface
上绘制从Engine
中提交的layer tree。合成器上下文和屏上绘制Surface
是Rasterizer
的主要组成部分:合成器上下文包含绘制帧的全部必要的GPU状态。
on_create_rasterizer
方法在AndroidShellHolder
的构造方法中给出:
// ./shell/platform/android/android_shell_holder.cc Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) { return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners()); };
// ./shell/common/rasterizer.cc Rasterizer::Rasterizer(Delegate& delegate, TaskRunners task_runners) : Rasterizer(delegate, std::move(task_runners), std::make_unique<flutter::CompositorContext>( delegate.GetFrameBudget())) { } Rasterizer::Rasterizer( Delegate& delegate, TaskRunners task_runners, std::unique_ptr<flutter::CompositorContext> 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
,这个类会在后续的文章中分析渲染机制时进行分析。
// ./shell/common/shell_io_manager.cc class ShellIOManager final : public IOManager { ... void NotifyResourceContextAvailable(sk_sp<GrContext> resource_context); void UpdateResourceContext(sk_sp<GrContext> resource_context); ... fml::WeakPtr<GrContext> GetResourceContext() const override; fml::RefPtr<flutter::SkiaUnrefQueue> GetSkiaUnrefQueue() const override; }
ShellIOManager
继承自IOManager
类。IOManager
是管理获取GrContext资源和Skia队列的方法的接口类。这二者都属于图形绘制相关内容,在后续文章中进行分析。
NotifyResourceContextAvailable
和UpdateResourceContext
方法是通知GrContext
建立和获取的方法。
Engine
类是Shell
的组成部分之一,运行于UI线程。其主要功能是管理根Isolate
和它的运行时。每一个Shell
只能拥有一个Engine
实例。Flutter应用的根Isolate
会获取“窗口”绑定。经过这些绑定,一个用能够调度帧、推送layer tree用于渲染、请求解压图片并提交到GPU等等。
Engine
管理根Isolate
的所有生命周期。当Engine
被回收时,其持有者会认为根Isolate
已经关闭且资源已经被回收。
下面看一下Engine
的构造方法:
// ./shell/common/engine.cc Engine::Engine(Delegate& delegate, const PointerDataDispatcherMaker& dispatcher_maker, DartVM& vm, fml::RefPtr<const DartSnapshot> isolate_snapshot, TaskRunners task_runners, const WindowData window_data, Settings settings, std::unique_ptr<Animator> animator, fml::WeakPtr<IOManager> io_manager, fml::RefPtr<SkiaUnrefQueue> unref_queue, fml::WeakPtr<SnapshotDelegate> snapshot_delegate) : delegate_(delegate), settings_(std::move(settings)), animator_(std::move(animator)), activity_running_(true), have_surface_(false), image_decoder_(task_runners, vm.GetConcurrentWorkerTaskRunner(), 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<RuntimeController>( *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
。
启动流程从FLutterActivity
的onStart
方法开始分析。
先看onStart
方法代码:
// ./shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @Override protected void onStart() { super.onStart(); lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START); delegate.onStart(); }
该方法先将生命周期调整为ON_START
状态,而后调用FlutterActivityAndFragmentDelegate
的onStart
方法。
下面是FlutterActivityAndFragmentDelegate
的onStart
方法:
// ./shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java void onStart() { ensureAlive(); doInitialFlutterViewRun(); }
这里先作了活动确认,后启动FlutterView
内的Dart。
// ./shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java private void doInitialFlutterViewRun() { ... if (flutterEngine.getDartExecutor().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. DartExecutor.DartEntrypoint entrypoint = new DartExecutor.DartEntrypoint( host.getAppBundlePath(), host.getDartEntrypointFunctionName()); flutterEngine.getDartExecutor().executeDartEntrypoint(entrypoint); // [9] }
由于在指定的FlutterView
中不支持重载或者重启Dart,因此须要先对DartExecutor
判断是否正在执行代码。
FlutterActivity
中获取应用包路径和Dart入口方法,建立DartEntrypoint
。根据这个DartEntrypoint
执行Dart代码。DartExecutor
在FlutterEngine
建立的时候建立出来,并在dartExecutor.onAttachedToJNI
方法中,将DartMessager
设置到FlutterJNI
中。
// ./shell/platform/android/io/flutter/embedding/engine/dart/DartExecutor.java public void executeDartEntrypoint(@NonNull DartEntrypoint dartEntrypoint) { ... flutterJNI.runBundleAndSnapshotFromLibrary( dartEntrypoint.pathToBundle, dartEntrypoint.dartEntrypointFunctionName, null, assetManager); ... }
继续调用FlutterJNI
的runBundleAndSnapshotFromLibrary
方法。
FlutterJNI
对线程和本地绑定确认后,调用native方法nativeRunBundleAndSnapshotFromLibrary
。通过AndroidShellHolder
的Launch
调用后,最终会调用到Shell
的RunEngine
方法。
下面看一下RunEngine
方法:
// ./shell/common/shell.cc void Shell::RunEngine(RunConfiguration run_configuration) { RunEngine(std::move(run_configuration), nullptr); } void Shell::RunEngine( RunConfiguration run_configuration, const std::function<void(Engine::RunStatus)>& 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); })); }
Engine
是建立、运行都在UI线程中的。因此此处Engine
执行Dart代码须要在UI线程中执行。// ./shell/common/engine.cc Engine::RunStatus Engine::Run(RunConfiguration configuration) { ... last_entry_point_ = configuration.GetEntrypoint(); last_entry_point_library_ = configuration.GetEntrypointLibrary(); auto isolate_launch_status = PrepareAndLaunchIsolate(std::move(configuration)); // [11] ... std::shared_ptr<DartIsolate> 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<PlatformMessage> service_id_message = fml::MakeRefCounted<flutter::PlatformMessage>( kIsolateChannel, // 此处设置为IsolateChannel std::vector<uint8_t>(service_id.begin(), service_id.end()), 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/engine.cc Engine::RunStatus Engine::PrepareAndLaunchIsolate( RunConfiguration configuration) { UpdateAssetManager(configuration.GetAssetManager()); auto isolate_configuration = configuration.TakeIsolateConfiguration(); std::shared_ptr<DartIsolate> isolate = runtime_controller_->GetRootIsolate().lock(); ... if (!isolate_configuration->PrepareIsolate(*isolate)) { return RunStatus::Failure; } if (configuration.GetEntrypointLibrary().empty()) { // 以前传入的library为空,进入该分支 if (!isolate->Run(configuration.GetEntrypoint(), settings_.dart_entrypoint_args)) { return RunStatus::Failure; } } else { if (!isolate->RunFromLibrary(configuration.GetEntrypointLibrary(), configuration.GetEntrypoint(), settings_.dart_entrypoint_args)) { return RunStatus::Failure; } } }
在该方法中,通过对Isolate
的一系列状态判断后,执行了Run
方法:
// ./runtime/dart_isolate.cc [[nodiscard]] bool DartIsolate::Run(const std::string& entrypoint_name, const std::vector<std::string>& 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_isolate.cc [[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; }
到此,就完成了引擎的初始化和启动流程。
本篇文章主要分析了Flutter引擎的初始化和启动流程。
能够看出,在Flutter引擎中,Shell
最重要的类,掌控对系统平台的适配和基本逻辑的控制。 在后续文章中,我会对Flutter的一些基本内容,如UI系统、消息机制、图形系统等等,进行详细分析。