Framework的启动
本文也发布于本人的知乎专栏:https://zhuanlan.zhihu.com/p/394564792
0. 前言
在我之前的文章Flutter源码阅读分析:引擎初始化与启动的最后,提到了在引擎启动时,会以“main”方法作为主入口函数,执行Dart代码。那么本片文章就从“main”方法着手,分析Dart Framework具体做了什么。
Framework代码:https://github.com/flutter/flutter
1. runApp
首先我们从flutter官方给的例子来看:
// ./examples/hello_world/lib/main.dart
void main() =>
runApp( //[1]
const Center( // [2]
child:
Text('Hello, world!',
key: Key('title'),
textDirection: TextDirection.ltr
)
)
);
- [1]
runApp
方法的主要功能是填充给定的Widget
并将其附到屏幕上。 - [2]
Center
是一种将子节点置于中心的Align
,这些都是Fllutter的Widget系统,这个在后文中详细分析。
此处先看runApp
做了什么:
// ./packages/flutter/lib/src/widgets/binging.dart
void runApp(Widget app) {
WidgetsFlutterBinding.ensureInitialized()
..scheduleAttachRootWidget(app)
..scheduleWarmUpFrame();
}
如果重复调用runApp
方法,那么会将之前的根Widget
从屏幕中移除,并将新的指定的Widget
替换到该位置。这个新的Widget树与前者进行对比,并将区别的地方应用到后续的渲染树。这里涉及到Flutter的布局渲染机制,会在后续讲解。
WidgetsFlutterBinding
类是基于Widget框架的应用程序的具体绑定。这将框架和Flutter引擎绑定起来。
// ./packages/flutter/lib/src/widgets/binding.dart
class WidgetsFlutterBinding extends BindingBase with GestureBinding, SchedulerBinding, ServicesBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding {
static WidgetsBinding ensureInitialized() {
if (WidgetsBinding.instance == null)
WidgetsFlutterBinding();
return WidgetsBinding.instance;
}
}
ensureInitialized
方法返回一个WidgetBinding
的实例。
再看一下scheduleAttachRootWidget
和scheduleWarmUpFrame
方法:
// ./packages/flutter/lib/src/widgets/binding.dart
mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, RendererBinding, SemanticsBinding {
...
// 通过Timer安排一个任务,用于执行附着根Widget
@protected
void scheduleAttachRootWidget(