本文主要是針對 Flutter 在 iOS 上是如何運行起來的源碼進行串聯,總結大體的運行流程。c++
涉及到的關鍵類有如下幾個:git
Flutter 嵌入原生應用必須有個載體,從這個點入手,在 Flutter Engine 源碼中的 API 的入口點是 FlutterViewController
,對其頭文件源碼作精簡,大體以下github
@interface FlutterViewController : UIViewController <FlutterTextureRegistry, FlutterPluginRegistry> - (instancetype)initWithEngine:(FlutterEngine*)engine nibName:(nullable NSString*)nibName bundle:(nullable NSBundle*)nibBundle NS_DESIGNATED_INITIALIZER; - (instancetype)initWithProject:(nullable FlutterDartProject*)project nibName:(nullable NSString*)nibName bundle:(nullable NSBundle*)nibBundle NS_DESIGNATED_INITIALIZER; - (void)handleStatusBarTouches:(UIEvent*)event; - (void)setFlutterViewDidRenderCallback:(void (^)(void))callback; - (NSString*)lookupKeyForAsset:(NSString*)asset; - (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package; - (void)setInitialRoute:(NSString*)route; - (void)popRoute; - (void)pushRoute:(NSString*)route; - (id<FlutterPluginRegistry>)pluginRegistry; @property(nonatomic, readonly, getter=isDisplayingFlutterUI) BOOL displayingFlutterUI; @property(strong, nonatomic) UIView* splashScreenView; - (BOOL)loadDefaultSplashScreenView; @property(nonatomic, getter=isViewOpaque) BOOL viewOpaque; @property(weak, nonatomic, readonly) FlutterEngine* engine; @property(nonatomic, readonly) NSObject<FlutterBinaryMessenger>* binaryMessenger; @end
FlutterViewController 有兩個構造函數,本質上是同樣的,第一個構造函數是谷歌爲了在存在多個 FlutterViewController
的場景下爲了讓使用者能複用 FlutterEngine
而開放的。web
- (instancetype)initWithEngine:(FlutterEngine*)engine nibName:(nullable NSString*)nibName bundle:(nullable NSBundle*)nibBundle { NSAssert(engine != nil, @"Engine is required"); self = [super initWithNibName:nibName bundle:nibBundle]; if (self) { _viewOpaque = YES; _engine.reset([engine retain]); _engineNeedsLaunch = NO; _flutterView.reset([[FlutterView alloc] initWithDelegate:_engine opaque:self.isViewOpaque]); _weakFactory = std::make_unique<fml::WeakPtrFactory<FlutterViewController>>(self); _ongoingTouches = [[NSMutableSet alloc] init]; [self performCommonViewControllerInitialization]; [engine setViewController:self]; } return self; } - (instancetype)initWithProject:(nullable FlutterDartProject*)project nibName:(nullable NSString*)nibName bundle:(nullable NSBundle*)nibBundle { self = [super initWithNibName:nibName bundle:nibBundle]; if (self) { _viewOpaque = YES; _weakFactory = std::make_unique<fml::WeakPtrFactory<FlutterViewController>>(self); _engine.reset([[FlutterEngine alloc] initWithName:@"io.flutter" project:project allowHeadlessExecution:NO]); _flutterView.reset([[FlutterView alloc] initWithDelegate:_engine opaque:self.isViewOpaque]); [_engine.get() createShell:nil libraryURI:nil]; _engineNeedsLaunch = YES; _ongoingTouches = [[NSMutableSet alloc] init]; [self loadDefaultSplashScreenView]; [self performCommonViewControllerInitialization]; } return self; }
在構造函數中主要作了這麼幾件事情:shell
FlutterEngine
FlutterView
FlutterEngine
的構造函數沒有這項,應該是考慮了多 FlutterViewController
的場景下很差頻繁加載閃屏頁UIInterfaceOrientationMask
和 UIStatusBarStyle
Application
的生命週期,鍵盤事件,Accessibility
的事件等FlutterViewController
設置給 FlutterEngine
第二個構造函數中還多了這行代碼,第一個構造函數把這個調用延後了而已json
[_engine.get() createShell:nil libraryURI:nil];
在 loadView
函數中,設置了 FlutterViewController
的 view
,並判斷是否須要加載閃屏頁,能夠經過重寫 splashScreenView
的 get 方法返回 nil
的方式完全不加載閃屏頁segmentfault
- (void)loadView { self.view = _flutterView.get(); self.view.multipleTouchEnabled = YES; self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self installSplashScreenViewIfNecessary]; }
FlutterViewController
提供了三個接口容許咱們在原生端對 dart 的 Navigator
直接進行操做api
- (void)setInitialRoute:(NSString*)route { [[_engine.get() navigationChannel] invokeMethod:@"setInitialRoute" arguments:route]; } - (void)popRoute { [[_engine.get() navigationChannel] invokeMethod:@"popRoute" arguments:nil]; } - (void)pushRoute:(NSString*)route { [[_engine.get() navigationChannel] invokeMethod:@"pushRoute" arguments:route]; }
setInitialRoute
在 iOS 端經過 navigationChannel
來告訴 dart 具體的 initialRoute,這個過程略微特殊,並不會在 dart 端直接接收 channel 信息,
而是在引擎層面作了處理,web_ui 不在本文的解析範疇,這裏直接洗跟原生相關的點app
setInitialRoute
設置流程以下:less
DispatchPlatformMessage
-> HandleNavigationPlatformMessage
-> initial_route_
void Engine::DispatchPlatformMessage(fml::RefPtr<PlatformMessage> message) { if (message->channel() == kLifecycleChannel) { if (HandleLifecyclePlatformMessage(message.get())) return; } else if (message->channel() == kLocalizationChannel) { if (HandleLocalizationPlatformMessage(message.get())) return; } else if (message->channel() == kSettingsChannel) { HandleSettingsPlatformMessage(message.get()); return; } if (runtime_controller_->IsRootIsolateRunning() && runtime_controller_->DispatchPlatformMessage(std::move(message))) { return; } // If there's no runtime_, we may still need to set the initial route. if (message->channel() == kNavigationChannel) { HandleNavigationPlatformMessage(std::move(message)); return; } FML_DLOG(WARNING) << "Dropping platform message on channel: " << message->channel(); }
bool Engine::HandleNavigationPlatformMessage( fml::RefPtr<PlatformMessage> message) { const auto& data = message->data(); rapidjson::Document document; document.Parse(reinterpret_cast<const char*>(data.data()), data.size()); if (document.HasParseError() || !document.IsObject()) return false; auto root = document.GetObject(); auto method = root.FindMember("method"); if (method->value != "setInitialRoute") return false; auto route = root.FindMember("args"); initial_route_ = std::move(route->value.GetString()); return true; }
setInitialRoute
最終在 HandleNavigationPlatformMessage
函數中直接被賦值給 initial_route_
。
setInitialRoute
讀取流程以下:
Window.defaultRouteName
-> DefaultRouteName
-> Engine::DefaultRouteName
-> initial_route_
能夠看到,關鍵字 native
,這是 dart 爲了方便綁定 C/C++ 導出方法而添加的關鍵字,對應的 key 是 Window_defaultRouteName
class Window { String get defaultRouteName => _defaultRouteName(); String _defaultRouteName() native 'Window_defaultRouteName'; }
能夠找到在引擎層的 flutter 命名空間下,有下面這個函數,註冊了對應的導出函數,這裏對應的是 DefaultRouteName
void Window::RegisterNatives(tonic::DartLibraryNatives* natives) { natives->Register({ {"Window_defaultRouteName", DefaultRouteName, 1, true}, {"Window_scheduleFrame", ScheduleFrame, 1, true}, {"Window_sendPlatformMessage", _SendPlatformMessage, 4, true}, {"Window_respondToPlatformMessage", _RespondToPlatformMessage, 3, true}, {"Window_render", Render, 2, true}, {"Window_updateSemantics", UpdateSemantics, 2, true}, {"Window_setIsolateDebugName", SetIsolateDebugName, 2, true}, {"Window_reportUnhandledException", ReportUnhandledException, 2, true}, {"Window_setNeedsReportTimings", SetNeedsReportTimings, 2, true}, }); }
void DefaultRouteName(Dart_NativeArguments args) { std::string routeName = UIDartState::Current()->window()->client()->DefaultRouteName(); Dart_SetReturnValue(args, tonic::StdStringToDart(routeName)); }
再往下就是到 engine.cc 文件下面的函數,讀取 initial_route_
的值
std::string Engine::DefaultRouteName() { if (!initial_route_.empty()) { return initial_route_; } return "/"; }
至此,完成了在原生端設置 defaultRouteName,在 dart 端獲取該值的流程。
實現方式主要仍是經過引擎內置的 navigationChannel
通知 dart 端,對應的在 dart 端 SystemChannels
類中,存在對應的 channel
static const MethodChannel navigation = MethodChannel( 'flutter/navigation', JSONMethodCodec(), );
最終處理 pushRoute
和 popRoute
的邏輯在 WidgetsBinding
類中,主要是如下幾個函數
Future<dynamic> _handleNavigationInvocation(MethodCall methodCall) { switch (methodCall.method) { case 'popRoute': return handlePopRoute(); case 'pushRoute': return handlePushRoute(methodCall.arguments as String); } return Future<dynamic>.value(); } Future<void> handlePushRoute(String route) async { for (final WidgetsBindingObserver observer in List<WidgetsBindingObserver>.from(_observers)) { if (await observer.didPushRoute(route)) return; } } Future<void> handlePopRoute() async { for (final WidgetsBindingObserver observer in List<WidgetsBindingObserver>.from(_observers)) { if (await observer.didPopRoute()) return; } SystemNavigator.pop(); }
這段代碼表示只有調用的方法返回 true
時才中斷,每一個 handle 函數具體的處理邏輯是經過某個 WidgetsBindingObserver
來實現了,繼續跟進找到以下代碼
class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver { @override Future<bool> didPopRoute() async { assert(mounted); final NavigatorState navigator = _navigator?.currentState; if (navigator == null) return false; return await navigator.maybePop(); } @override Future<bool> didPushRoute(String route) async { assert(mounted); final NavigatorState navigator = _navigator?.currentState; if (navigator == null) return false; navigator.pushNamed(route); return true; } }
handlePopRoute
函數中,若是沒有任何一個 observer
返回 true
,則最終調用 SystemNavigator.pop();
來退出應用程序
class SystemNavigator { static Future<void> pop({bool animated}) async { await SystemChannels.platform.invokeMethod<void>('SystemNavigator.pop', animated); } }
FlutterView
並無太多功能,主要是兩點:
FlutterViewEngineDelegate
flutter::IOSSurface
@protocol FlutterViewEngineDelegate <NSObject> - (flutter::Rasterizer::Screenshot)takeScreenshot:(flutter::Rasterizer::ScreenshotType)type asBase64Encoded:(BOOL)base64Encode; - (flutter::FlutterPlatformViewsController*)platformViewsController; @end @interface FlutterView : UIView - (instancetype)initWithDelegate:(id<FlutterViewEngineDelegate>)delegate opaque:(BOOL)opaque NS_DESIGNATED_INITIALIZER; - (std::unique_ptr<flutter::IOSSurface>)createSurface: (std::shared_ptr<flutter::IOSGLContext>)context; @end
takeScreenshot:asBase64Encoded:
應該是 FlutterView
渲染的數據源,具體參考 drawLayer:inContext:
的源碼
@implementation FlutterView - (void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context { if (layer != self.layer || context == nullptr) { return; } auto screenshot = [_delegate takeScreenshot:flutter::Rasterizer::ScreenshotType::UncompressedImage asBase64Encoded:NO]; if (!screenshot.data || screenshot.data->isEmpty() || screenshot.frame_size.isEmpty()) { return; } NSData* data = [NSData dataWithBytes:const_cast<void*>(screenshot.data->data()) length:screenshot.data->size()]; fml::CFRef<CGDataProviderRef> image_data_provider( CGDataProviderCreateWithCFData(reinterpret_cast<CFDataRef>(data))); fml::CFRef<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB()); fml::CFRef<CGImageRef> image(CGImageCreate( screenshot.frame_size.width(), // size_t width screenshot.frame_size.height(), // size_t height 8, // size_t bitsPerComponent 32, // size_t bitsPerPixel, 4 * screenshot.frame_size.width(), // size_t bytesPerRow colorspace, // CGColorSpaceRef space static_cast<CGBitmapInfo>(kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big), // CGBitmapInfo bitmapInfo image_data_provider, // CGDataProviderRef provider nullptr, // const CGFloat* decode false, // bool shouldInterpolate kCGRenderingIntentDefault // CGColorRenderingIntent intent )); const CGRect frame_rect = CGRectMake(0.0, 0.0, screenshot.frame_size.width(), screenshot.frame_size.height()); CGContextSaveGState(context); CGContextTranslateCTM(context, 0.0, CGBitmapContextGetHeight(context)); CGContextScaleCTM(context, 1.0, -1.0); CGContextDrawImage(context, frame_rect, image); CGContextRestoreGState(context); } @end
後面咱們會看到 FlutterViewEngineDelegate
其實是被 FlutterEngine
實現了。
這裏不對 IOSSurface
作過多解析,其是創建在三種 layer 之上的,能夠在編譯期選擇使用何種渲染方式
+ (Class)layerClass { #if TARGET_IPHONE_SIMULATOR return [CALayer class]; #else // TARGET_IPHONE_SIMULATOR #if FLUTTER_SHELL_ENABLE_METAL return [CAMetalLayer class]; #else // FLUTTER_SHELL_ENABLE_METAL return [CAEAGLLayer class]; #endif // FLUTTER_SHELL_ENABLE_METAL #endif // TARGET_IPHONE_SIMULATOR }
在 createSurface
函數中主要是分別建立三種對應的 IOSSurface
CALayer -> IOSSurfaceSoftware
CAEAGLLayer -> IOSSurfaceGL
CAMetalLayer -> IOSSurfaceMetal
再往下的渲染實際上就要交給 FlutterEngine
自身了。
FlutterEngine
對外暴露的接口不算多,主要就這麼幾點
initWithName:project:allowHeadlessExecution
,allowHeadlessExecution容許初始化引擎時不強依賴
FlutterViewController`runWithEntrypoint:libraryURI:
可傳入自定義的 entrypoint
destroyContext
ensureSemanticsEnabled
,關於語義樹文檔比較少,大概是殘疾人模式下須要用到的東西FlutterViewController
的 get/set咱們主要關心引擎的構造、啓動、釋放和 FlutterViewController
就差很少了,FlutterTextureRegistry
, FlutterPluginRegistry
不在本文關注範圍內
@interface FlutterEngine : NSObject <FlutterTextureRegistry, FlutterPluginRegistry> - (instancetype)initWithName:(NSString*)labelPrefix project:(nullable FlutterDartProject*)project allowHeadlessExecution:(BOOL)allowHeadlessExecution NS_DESIGNATED_INITIALIZER; - (BOOL)runWithEntrypoint:(nullable NSString*)entrypoint libraryURI:(nullable NSString*)uri; - (void)destroyContext; - (void)ensureSemanticsEnabled; @property(nonatomic, weak) FlutterViewController* viewController; @property(nonatomic, readonly, nullable) FlutterMethodChannel* localizationChannel; @property(nonatomic, readonly) FlutterMethodChannel* navigationChannel; @property(nonatomic, readonly) FlutterMethodChannel* platformChannel; @property(nonatomic, readonly) FlutterMethodChannel* textInputChannel; @property(nonatomic, readonly) FlutterBasicMessageChannel* lifecycleChannel; @property(nonatomic, readonly) FlutterBasicMessageChannel* systemChannel; @property(nonatomic, readonly) FlutterBasicMessageChannel* settingsChannel; @property(nonatomic, readonly) NSObject<FlutterBinaryMessenger>* binaryMessenger; @property(nonatomic, readonly, copy, nullable) NSString* isolateId; @end
FlutterEngine
在構造時,要關注的有幾下兩點:
FlutterDartProject
初始化FlutterPlatformViewsController
的初始化- (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)project allowHeadlessExecution:(BOOL)allowHeadlessExecution { self = [super init]; NSAssert(self, @"Super init cannot be nil"); NSAssert(labelPrefix, @"labelPrefix is required"); _allowHeadlessExecution = allowHeadlessExecution; _labelPrefix = [labelPrefix copy]; _weakFactory = std::make_unique<fml::WeakPtrFactory<FlutterEngine>>(self); if (project == nil) _dartProject.reset([[FlutterDartProject alloc] init]); else _dartProject.reset([project retain]); _pluginPublications = [NSMutableDictionary new]; _platformViewsController.reset(new flutter::FlutterPlatformViewsController()); _binaryMessenger = [[FlutterBinaryMessengerRelay alloc] initWithParent:self]; NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; [center addObserver:self selector:@selector(onMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; return self; }
FlutterEngine
層面,須要關注如下一些類:
FlutterEngine
的啓動,主要是兩個事情
- (BOOL)runWithEntrypoint:(NSString*)entrypoint libraryURI:(NSString*)libraryURI { if ([self createShell:entrypoint libraryURI:libraryURI]) { [self launchEngine:entrypoint libraryURI:libraryURI]; } return _shell != nullptr; }
createShell
的源碼比較多,作了下精簡,主要是如下幾點:
MessageLoop
ThreadHost
on_create_platform_view
回調on_create_rasterizer
回調flutter::TaskRunners
,若是開啓 embedded_views_preview
則 使用當前線程的 TaskRunner
做爲 gpu 線程的 TaskRunner
shell
,最終是啓動 IsolateFlutterPlatformViewsController
FlutterObservatoryPublisher
PlatformView
channels- (BOOL)createShell:(NSString*)entrypoint libraryURI:(NSString*)libraryURI { // …… fml::MessageLoop::EnsureInitializedForCurrentThread(); _threadHost = {threadLabel.UTF8String, flutter::ThreadHost::Type::UI | flutter::ThreadHost::Type::GPU | flutter::ThreadHost::Type::IO}; flutter::Shell::CreateCallback<flutter::PlatformView> on_create_platform_view = [](flutter::Shell& shell) { return std::make_unique<flutter::PlatformViewIOS>(shell, shell.GetTaskRunners()); }; flutter::Shell::CreateCallback<flutter::Rasterizer> on_create_rasterizer = [](flutter::Shell& shell) { return std::make_unique<flutter::Rasterizer>(shell, shell.GetTaskRunners()); }; if (flutter::IsIosEmbeddedViewsPreviewEnabled()) { flutter::TaskRunners task_runners(threadLabel.UTF8String, // label fml::MessageLoop::GetCurrent().GetTaskRunner(), // platform fml::MessageLoop::GetCurrent().GetTaskRunner(), // gpu _threadHost.ui_thread->GetTaskRunner(), // ui _threadHost.io_thread->GetTaskRunner() // io ); // Create the shell. This is a blocking operation. _shell = flutter::Shell::Create(std::move(task_runners), // task runners std::move(settings), // settings on_create_platform_view, // platform view creation on_create_rasterizer // rasterzier creation ); } else { flutter::TaskRunners task_runners(threadLabel.UTF8String, // label fml::MessageLoop::GetCurrent().GetTaskRunner(), // platform _threadHost.gpu_thread->GetTaskRunner(), // gpu _threadHost.ui_thread->GetTaskRunner(), // ui _threadHost.io_thread->GetTaskRunner() // io ); // Create the shell. This is a blocking operation. _shell = flutter::Shell::Create(std::move(task_runners), // task runners std::move(settings), // settings on_create_platform_view, // platform view creation on_create_rasterizer // rasterzier creation ); } if (_shell != nullptr) { [self setupChannels]; if (!_platformViewsController) { _platformViewsController.reset(new flutter::FlutterPlatformViewsController()); } _publisher.reset([[FlutterObservatoryPublisher alloc] init]); [self maybeSetupPlatformViewChannels]; } return _shell != nullptr; }
這裏能夠看到會啓動四個 TaskRunner
,分別爲 platform,gpu, ui,io,但實際上並不必定對應四個線程。
launchEngine
實際上仍是在 shell
上進行的操做
- (void)launchEngine:(NSString*)entrypoint libraryURI:(NSString*)libraryOrNil { // Launch the Dart application with the inferred run configuration. self.shell.RunEngine([_dartProject.get() runConfigurationForEntrypoint:entrypoint libraryOrNil:libraryOrNil]); }
void Shell::RunEngine(RunConfiguration run_configuration) { RunEngine(std::move(run_configuration), nullptr); } void Shell::RunEngine(RunConfiguration run_configuration, std::function<void(Engine::RunStatus)> result_callback) { 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_setup_); FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); if (!weak_engine_) { result(Engine::RunStatus::Failure); } fml::TaskRunner::RunNowOrPostTask( task_runners_.GetUITaskRunner(), fml::MakeCopyable( [run_configuration = std::move(run_configuration), weak_engine = weak_engine_, result]() mutable { if (!weak_engine) { FML_LOG(ERROR) << "Could not launch engine with configuration - no engine."; result(Engine::RunStatus::Failure); return; } 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); })); }
再跟下去,最終會到[shell > common > engine.cc] 裏面的 run
函數,最核心的是這行代碼 PrepareAndLaunchIsolate
,最終整個流程跑下來就是爲了啓動 Isolate
Engine::RunStatus Engine::Run(RunConfiguration configuration) { if (!configuration.IsValid()) { FML_LOG(ERROR) << "Engine run configuration was invalid."; return RunStatus::Failure; } auto isolate_launch_status = PrepareAndLaunchIsolate(std::move(configuration)); if (isolate_launch_status == Engine::RunStatus::Failure) { FML_LOG(ERROR) << "Engine not prepare and launch isolate."; return isolate_launch_status; } else if (isolate_launch_status == Engine::RunStatus::FailureAlreadyRunning) { return isolate_launch_status; } std::shared_ptr<DartIsolate> isolate = runtime_controller_->GetRootIsolate().lock(); bool isolate_running = isolate && isolate->GetPhase() == DartIsolate::Phase::Running; if (isolate_running) { tonic::DartState::Scope scope(isolate.get()); if (settings_.root_isolate_create_callback) { settings_.root_isolate_create_callback(); } if (settings_.root_isolate_shutdown_callback) { isolate->AddIsolateShutdownCallback( settings_.root_isolate_shutdown_callback); } std::string service_id = isolate->GetServiceId(); fml::RefPtr<PlatformMessage> service_id_message = fml::MakeRefCounted<flutter::PlatformMessage>( kIsolateChannel, std::vector<uint8_t>(service_id.begin(), service_id.end()), nullptr); HandlePlatformMessage(service_id_message); } return isolate_running ? Engine::RunStatus::Success : Engine::RunStatus::Failure; }
對 PrepareAndLaunchIsolate
函數作下精簡,剩下兩個點
Engine::RunStatus Engine::PrepareAndLaunchIsolate(RunConfiguration configuration) { // …… if (!isolate_configuration->PrepareIsolate(*isolate)) { return RunStatus::Failure; } if (!isolate->RunFromLibrary(configuration.GetEntrypointLibrary(), configuration.GetEntrypoint(), settings_.dart_entrypoint_args)) { return RunStatus::Failure; } return RunStatus::Success; }
主要看看 RunFromLibrary
作了什麼
InvokeMainEntrypoint
bool DartIsolate::RunFromLibrary(const std::string& library_name, const std::string& entrypoint_name, const std::vector<std::string>& args, fml::closure on_run) { tonic::DartState::Scope scope(this); auto user_entrypoint_function = Dart_GetField(Dart_LookupLibrary(tonic::ToDart(library_name.c_str())), 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; }
再看看 InvokeMainEntrypoint
作了什麼,源碼作了精簡,主要就這兩步,咱們能夠在 dart 端找到對應的函數
_getStartMainIsolateFunction
_runMainZoned
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}))) { FML_LOG(ERROR) << "Could not invoke the main entrypoint."; return false; } return true; }
再往下就是 tonic 庫,這是 fuchsia 下的庫,谷歌並未開源到 github 上,但能夠在這裏看到 googlesource,後面可能會在其它文章中對 tonic 庫進行梳理。
Flutter 運行於 iOS 之上,從源碼層面看,有如下幾點收穫:
drawLayer
時會調用 takeScreenshot
來獲取 Flutter 界面的光柵圖TaskRunner
,Platform TaskRunner 不必定是獨立的線程native
關鍵字調用 C/C++ 的函數,獲取基本類型的數據返回值,性能比 channel 要好FlutterViewController
將全部的手勢交互相關的都轉發給 FlutterEngine對整個 Flutter 運行的流程能夠大體總結以下,主要是側重在引擎側,dart 那邊的流程不展開,僅供參考:
FlutterEngine
,傳入 DartLibrary 和 EntrypointFlutterViewController
,FlutterView
FlutterEngine
的 viewController
做者其它文章