首先开启启动原生的应用,然后初始化flutter engine,之后在开启4个Task Runners分别是
Platform Task Runner: 跟Flutter Engine的所有交互(接口调用)必须发生在Platform Thread,对应的native的主线程
UI Task Runner Thread(Dart Runner): UI Task Runner被Flutter Engine用于执行Dart root isolate代码
GPU Task Runner: 被用于执行设备GPU的相关调用
FlutterEngine加之后, 开始执行main函数
IO Task Runner: 负责磁盘数据的读取,主要是图片,提前处理减轻GPU的压力
下面主要是UI Task Runner
下的启动过程,其他几个TaskRunner大都在FlutterEngine层
Flutter main函数
它首先创建了一个MaterailApp
,通常会叫它根视图,其实最终它会作为真正的根视图的第一个child
然后执行WidgetsFlutterBinding,绑定flutterEngine的相关callback事件
构建ElementTree和RenderTree, WidgetTree在我们代码里就能看到了,由开发者调整。它们的先后顺序是 WidgetTree -> ElementTree -> RenderTree
然后通知Flutter Engine预热,刷新当前视图,而不是等待vsync信号
void main() {
runApp(
MaterialApp(
title: 'demo',
home: HomePage(),
),
);
}
void runApp(Widget app) {
WidgetsFlutterBinding.ensureInitialized()
..scheduleAttachRootWidget(app)
..scheduleWarmUpFrame();
}
1. 创建根RootWidget
1.1 这里一般定义为MaterialApp, 它初始化了很多属性它是一个使用material design的应用
const MaterialApp({
Key key,
this.navigatorKey,
this.home,
this.routes = const <String, WidgetBuilder>{},
this.initialRoute,
this.onGenerateRoute,
this.onGenerateInitialRoutes,
this.onUnknownRoute,
this.navigatorObservers = const <NavigatorObserver>[],
this.builder,
this.title = '',
this.onGenerateTitle,
this.color,
this.theme,
this.darkTheme,
this.themeMode = ThemeMode.system,
this.locale, //app的初始化local
this.localizationsDelegates,//设置app localizations的delegate,用于提供翻译字符串
this.localeListResolutionCallback,//app的local修改后的回调
this.localeResolutionCallback,//用于拦截修改当前支持的local
this.supportedLocales = const <Locale>[Locale('en', 'US')],//指定app支持哪些local,不指定则采用系统的local
this.debugShowMaterialGrid = false,
this.showPerformanceOverlay = false,
this.checkerboardRasterCacheImages = false,
this.checkerboardOffscreenLayers = false,
this.showSemanticsDebugger = false,
this.debugShowCheckedModeBanner = true,
this.shortcuts,
this.actions,
})
1.2 MaterialApp中的信息最终会传递给WdigetsApp, 具体实现在 _WidgetsAppState
_WidgetsAppState
@override
void initState() {
super.initState();
//创建GlobalKey,缓存rootnavigator
_updateNavigator();
//获取系统的local信息,并回调给materialApp
_locale = _resolveLocales(WidgetsBinding.instance.window.locales, widget.supportedLocales);
WidgetsBinding.instance.addObserver(this);
}
//创建Router
Route<dynamic> _onGenerateRoute(RouteSettings settings)
...
widget.onGenerateRoute(settings);
//创建unknownRoot
Route<dynamic> _onUnknownRoute(RouteSettings settings) {
//监听native的导航事件
Future<bool> didPopRoute() async //如果为android则为返回按键
Future<bool> didPushRoute(String route) async
//系统local处理
void didChangeLocales(List<Locale> locales) {
final Locale newLocale = _resolveLocales(locales, widget.supportedLocales);
//处理local
Locale _resolveLocales(List<Locale> preferredLocales, Iterable<Locale> supportedLocales) {
// 过滤local,用于修改local,如果取不到对应的local则采用相近的local
if (widget.localeListResolutionCallback != null) {
final Locale locale = widget.localeListResolutionCallback(preferredLocales, widget.supportedLocales);
//处理MaterialApp local回调信息,优先选择系统的默认local
if (widget.localeResolutionCallback != null) {
final Locale locale = widget.localeResolutionCallback(
preferredLocales != null && preferredLocales.isNotEmpty ? preferredLocales.first : null,
widget.supportedLocales,
);
1.3 根视图执行build方法, 构建Element的配置信息
- 可以看到根视图最终的Child的是一个
Navigator
, 而Navigator
会挂在一个可视化的rootWidget
, 通过initialRoute去查找。
Widget build(BuildContext context) {
Widget navigator;
if (_navigator != null) {
navigator = Navigator(
key: _navigator,
//优先选择native的routeName
initialRoute: WidgetsBinding.instance.window.defaultRouteName != Navigator.defaultRouteName
? WidgetsBinding.instance.window.defaultRouteName
: widget.initialRoute ?? WidgetsBinding.instance.window.defaultRouteName,
//设置route的构造方法
onGenerateRoute: _onGenerateRoute,
//设置initialRoute
onGenerateInitialRoutes: widget.onGenerateInitialRoutes == null
? Navigator.defaultGenerateInitialRoutes
: (NavigatorState navigator, String initialRouteName) {
return widget.onGenerateInitialRoutes(initialRouteName);
},
//设置位置的root
onUnknownRoute: _onUnknownRoute,
//设置navigator的观察者
observers: widget.navigatorObservers,
);
}
Widget result;
if (widget.builder != null) {
result = Builder(
builder: (BuildContext context) {
return widget.builder(context, navigator);
},
);
} else {
assert(navigator != null);
result = navigator;
}
//设置样式,DefaultTextStyle继承于InheritedTheme
if (widget.textStyle != null) {
result = DefaultTextStyle(
style: widget.textStyle,
child: result,
);
}
...
Widget title;
if (widget.onGenerateTitle != null) {
//转换child的context作用域,避免loaclizations widget构建失败
title = Builder(
builder: (BuildContext context) {
final String title = widget.onGenerateTitle(context);
assert(title != null, 'onGenerateTitle must return a non-null String');
return Title(
title: title,
color: widget.color,
child: result,
);
},
);
} else {
title = Title(
title: widget.title,
color: widget.color,
child: result,
);
}
final Locale appLocale = widget.locale != null
? _resolveLocales(<Locale>[widget.locale], widget.supportedLocales)
: _locale;
...
//捕捉用户意图
return Shortcuts(
shortcuts: widget.shortcuts ?? WidgetsApp.defaultShortcuts,
debugLabel: '<Default WidgetsApp Shortcuts>',
child: Actions(
actions: widget.actions ?? WidgetsApp.defaultActions,
child: FocusTraversalGroup(
policy: ReadingOrderTraversalPolicy(),
//获取native屏幕大小,绑定dart.ui window回调信息(textScale/brightness)
child: _MediaQueryFromWindow(
//通过引入_LocalizationsScope包装根视图 `Title` ,同时提供了local data给它的所有子widget
child: Localizations(
locale: appLocale,
delegates: _localizationsDelegates.toList(),
child: title,
),
),
),
),
);
}
2. 绑定FlutterEngine相关服务扩展
- 执行WidgetsFlutterBinding.ensureInitialized方法初始化, 在初始化方法中完成flutterEngine所有方法的绑定
- 创建全局单例类
WidgetsFlutterBinding
, 对应代码如下
//WidgetsFlutterBinding初始化对象 `this` 赋值给了 `WidgetsBinding.instance` ,通过类属性 `instance` 让它成为了全局单例子
WidgetsFlutterBinding();
return WidgetsBinding.instance;
WidgetsFlutterBinding关系图如下,通过mixin实现多重继承完成了FlutterEngine相关的事件绑定,它的绑定事件按照如下with从左到右的顺序一次绑定,由此可见
WidgetsBindings依赖的
FlutterEngine`服务最多, 因此它需要最后再绑定.
class WidgetsFlutterBinding extends BindingBase with GestureBinding, ServicesBinding, SchedulerBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding {
2.1 BindingBase:
提供最基本的服务订阅, 提供初始化 WidgetsBinding.instance
的方法
abstract class BindingBase {
BindingBase() {
//开启一个同步执行的Timeline,初始化flutterWidgets运行所必须的的订阅事件
//作为一个base class为子类提供断言
developer.Timeline.startSync('Framework initialization');
...
//初始化mixin相关的实例对象
initInstances();
...
//提供便利方法,执行 flutter engine提供的 `ext.flutter.$name` 方法
initServiceExtensions();
...
//通知native,widgets初始化完毕,可以开始绘制
developer.postEvent('Flutter.FrameworkInitialization', <String, String>{});
//解除Timeline的同步限制
developer.Timeline.finishSync();
}
//flutter engine提供的窗口,用于绑定native的service,监听flutter engine的回调事件
ui.Window get window => ui.window;
//定义一个抽象的方法,供mixin类初始化实例对象
@protected
@mustCallSuper
void initInstances() {
assert(() {
_debugInitialized = true;
return true;
}());
}
//注册flutter engine的扩展信息
@protected
@mustCallSuper
void initServiceExtensions() {
assert(!_debugServiceExtensionsRegistered);
assert(() {
//注册dart vm的 hot reload事件,用于debug时快速更新app
registerSignalServiceExtension(
name: 'reassemble',
callback: reassembleApplication,
);
return true;
}());
if (!kReleaseMode && !kIsWeb) {
//注册dart vm的退出事件
registerSignalServiceExtension(
name: 'exit',
callback: _exitApplication,
);
registerServiceExtension(
name: 'saveCompilationTrace',
callback: (Map<String, String> parameters) async {
return <String, dynamic>{
'value': ui.saveCompilationTrace(),
};
},
);
}
assert(() {
const String platformOverrideExtensionName = 'platformOverride';
//注册platformOverride的回调事件
registerServiceExtension(
name: platformOverrideExtensionName,
callback: (Map<String, String> parameters) async {
if (parameters.containsKey('value')) {
switch (parameters['value']) {
case 'android':
debugDefaultTargetPlatformOverride = TargetPlatform.android;
break;
case 'fuchsia':
debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia;
break;
case 'iOS':
debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
break;
case 'linux':
debugDefaultTargetPlatformOverride = TargetPlatform.linux;
break;
case 'macOS':
debugDefaultTargetPlatformOverride = TargetPlatform.macOS;
break;
case 'windows':
debugDefaultTargetPlatformOverride = TargetPlatform.windows;
break;
case 'default':
default:
debugDefaultTargetPlatformOverride = null;
}
_postExtensionStateChangedEvent(
platformOverrideExtensionName,
defaultTargetPlatform.toString().substring('$TargetPlatform.'.length),
);
await reassembleApplication();
}
return <String, dynamic>{
'value': defaultTargetPlatform
.toString()
.substring('$TargetPlatform.'.length),
};
},
);
return true;
}());
assert(() {
_debugServiceExtensionsRegistered = true;
return true;
}());
}
//定义Timeline的同步执行事件,通过lock数量控制是否将解除timeline的同步执行
//对关键操作提供同步执行操作
@protected
Future<void> lockEvents(Future<void> callback()) {
developer.Timeline.startSync('Lock events');
//调用shell的退出命令,关闭程序
Future<void> _exitApplication() async {
exit(0);
}
2.2 GestureBinding
- 注册手势的点击事件回调
mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, HitTestTarget {
@override
void initInstances() {
super.initInstances();
_instance = this;
window.onPointerDataPacket = _handlePointerDataPacket;
}
- 注册MethodChannel的回调
lifeCycle的监听, frame刷新
mixin ServicesBinding on BindingBase {
@override
void initInstances() {
super.initInstances();
_instance = this;
_defaultBinaryMessenger = createBinaryMessenger();
window.onPlatformMessage = defaultBinaryMessenger.handlePlatformMessage;
initLicenses();
SystemChannels.system.setMessageHandler(handleSystemMessage);
}
2.3 PaintingBinding
- 绑定绘制事件
mixin PaintingBinding on BindingBase, ServicesBinding {
@override
void initInstances() {
super.initInstances();
_instance = this;
_imageCache = createImageCache();
if (shaderWarmUp != null) {
shaderWarmUp.execute();
}
}
2.4 RendererBinding
- 绑定Render事件, 初始化根视图的
RenderObject
, 它比较特殊, 不同于一般的RenderObject, 因为需要提供窗口的大小, 所以系统对它进行了一次包装, 根据源码, 窗口的大小和deviceRatio就是在这个时候设置的
class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox> {
RenderView({
RenderBox child,
@required ViewConfiguration configuration,
@required ui.Window window,
})
mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, SemanticsBinding, HitTestable {
@override
void initInstances() {
super.initInstances();
_instance = this;
//初始化渲染管道owner,绑定flutter engine的绘制视图的回调事件
_pipelineOwner = PipelineOwner(
onNeedVisualUpdate: ensureVisualUpdate,
onSemanticsOwnerCreated: _handleSemanticsOwnerCreated,
onSemanticsOwnerDisposed: _handleSemanticsOwnerDisposed,
);
//绑定flutter engine的 文本大小,测量信息,屏幕亮度,语义行为事件
window
..onMetricsChanged = handleMetricsChanged
..onTextScaleFactorChanged = handleTextScaleFactorChanged
..onPlatformBrightnessChanged = handlePlatformBrightnessChanged
..onSemanticsEnabledChanged = _handleSemanticsEnabledChanged
..onSemanticsAction = _handleSemanticsAction;
//初始化renderRootObject
initRenderView();
_handleSemanticsEnabledChanged();
assert(renderView != null);
//监听系统的framecallback事件执行 `drawFrame`
addPersistentFrameCallback(_handlePersistentFrameCallback);
initMouseTracker();
}
WidgetsBindings
- 注册flutter engine widget相关的事件
mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, RendererBinding, SemanticsBinding {
@override
void initInstances() {
super.initInstances();
_instance = this;
...
_buildOwner = BuildOwner();
buildOwner.onBuildScheduled = _handleBuildScheduled;
window.onLocaleChanged = handleLocaleChanged;
window.onAccessibilityFeaturesChanged = handleAccessibilityFeaturesChanged;
SystemChannels.navigation.setMethodCallHandler(_handleNavigationInvocation);
FlutterErrorDetails.propertiesTransformers.add(transformDebugCreator);
3. 装配RootWidget
- 在
FlutterEngine
相关的Service绑定以后, 开始执行scheduleAttachRootWidget
, 这里通过Scheduler一个时间间隔为0的task来执行RootWidget绑定, Timer内部包装了一个_RootZone的环境,
//在初始化的时候根据deviceRatio和屏幕大小初始化Root renderObject,赋值给`PiplineOwner`
mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, SemanticsBinding, HitTestable {
set renderView(RenderView value) {
assert(value != null);
_pipelineOwner.rootNode = value;
}
void initRenderView() {
assert(renderView == null);
renderView = RenderView(configuration: createViewConfiguration(), window: window);
renderView.prepareInitialFrame();
}
...
mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, RendererBinding, SemanticsBinding {
void scheduleAttachRootWidget(Widget rootWidget) {
Timer.run(() {
attachRootWidget(rootWidget);
});
}
void attachRootWidget(Widget rootWidget) {
_readyToProduceFrames = true;
//根据RootRenderObject和RootWidget创建真正的RootWidget
_renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(
container: renderView, //此处renderView是RenderBinding在初始化的时候根据窗口大小还有设备像素比创建,并赋值给`_pipelineOwner`
debugShortDescription: '[root]',
child: rootWidget, //runApp传入的rootWidget
).attachToRenderTree(buildOwner, renderViewElement as RenderObjectToWidgetElement<RenderBox>);
} // buildOwner是在WidgetBindings创建,用于管理ElementTree更新
RenderObjectToWidgetElement<T> attachToRenderTree(BuildOwner owner, [ RenderObjectToWidgetElement<T> element ]) {
if (element == null) {
owner.lockState(() {
element = createElement();//创建RootElment
assert(element != null);
element.assignOwner(owner);
});
owner.buildScope(element, () {
element.mount(null, null);
});
// This is most likely the first time the framework is ready to produce
// a frame. Ensure that we are asked for one.
SchedulerBinding.instance.ensureVisualUpdate();
} else {
element._newWidget = this;
element.markNeedsBuild();
}
return element;
}
//每当element装配到ElementTree中时创建RenderObject
abstract class RenderObjectElement extends Element {
@override
void mount(Element parent, dynamic newSlot) {
super.mount(parent, newSlot);
assert(() {
_debugDoingBuild = true;
return true;
}());
_renderObject = widget.createRenderObject(this);
...
//然后将renderObject插入到它的先组上面,如此循环,最终形成了ElementTree和RrenderTree, ElmentTree节点更触发RenderTree节点的更新,Widget作为Element的配置信息,触发Element的更新。
@override
void attachRenderObject(dynamic newSlot) {
assert(_ancestorRenderObjectElement == null);
_slot = newSlot;
_ancestorRenderObjectElement = _findAncestorRenderObjectElement();
_ancestorRenderObjectElement?.insertChildRenderObject(renderObject, newSlot);
final ParentDataElement<ParentData> parentDataElement = _findAncestorParentDataElement();
if (parentDataElement != null)
_updateParentData(parentDataElement.widget);
}
根据上面的执行顺序可以看出, RootWidget
最先创建,然后是RootRenderObject
(PiplelineOwner负责管理RenderTree),
4. scheduleWarmUpFrame
- 向flutter主动请求刷新,而不是被动的通过vsync刷新
mixin SchedulerBinding on BindingBase, ServicesBinding {
void scheduleWarmUpFrame() {
if (_warmUpFrame || schedulerPhase != SchedulerPhase.idle)
return;
_warmUpFrame = true;
//用于开启一个同步事件,最终会提交一个event task到flutter engine
/**
// timeline.dart
external void _reportTaskEvent(int taskId, String phase, String category,
String name, String argumentsAsJson);
*/
Timeline.startSync('Warm-up frame');
final bool hadScheduledFrame = _hasScheduledFrame;
// We use timers here to ensure that microtasks flush in between.
Timer.run(() {
assert(_warmUpFrame);
handleBeginFrame(null); //通知flutter engine 刷新
});
Timer.run(() {
...
handleDrawFrame();
resetEpoch();
_warmUpFrame = false;
if (hadScheduledFrame)
scheduleFrame(); // window.scheduleFrame(); -> void scheduleFrame() native 'Window_scheduleFrame';
});
lockEvents(() async {
await endOfFrame;
Timeline.finishSync();
});
}
总结
Flutter App在启动时主要干了以下几件事情:
- 开启main isolate,在默认的mainZone内运行了main函数.
- 创建MaterialApp(或者是自定义的rootWidget)
- 绑定flutter engine相关的服务,系统点击事件,键盘,屏幕,亮度,字体,绘制回调,辅助提示,vsync信息,system.platform channels ...,详细参照启动时Widgetsbinding的几个mixin类的
initialServices
方法和dart.ui
- 构建RenderTree和ElementTree
- 主动通知flutter engine刷新屏幕