背景
Flutter的第一行程序开始, Dart的main方法中通过调用runApp方法把开发者自己编写的Widget传递进去, 编译运行后, 得到开发者预期的效果。我们很好奇, 这背后经历了什么?或者说, 你经常听到的Flutter三棵树核心机制是什么?接下来, 我们一起探讨。
Flutter程序入口
开发者自己编写的Flutter App一般入口都是在main方法, 其内部通过调用runApp方法将我们整个应用的Widget添加并运行。runApp的方法实现如下:
void runApp(Widget app) {
WidgetsFlutterBinding.ensureInitialized()
..scheduleAttachRootWidget(app)
..scheduleWarmUpFrame();
}
复制代码
上面三行代码代表Flutter启动的核心三步(级联运算符调用)
- WidgetsFlutterBinding初始化(ensureInitialized)
- 调度、绑定根节点, 创建核心三棵树(scheduleAttachRootWidget(app))
- 调度、绘制热身帧(scheduleWarmUpFrame())
WidgetsFlutterBinding实例及初始化
源码如下:
This is the glue that binds the framework to the Flutter engine.
class WidgetsFlutterBinding extends BindingBase with GestureBinding, SchedulerBinding, ServicesBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding {
static WidgetsBinding ensureInitialized() {
if (WidgetsBinding.instance == null)
WidgetsFlutterBinding();
return WidgetsBinding.instance!;
}
}
复制代码
分析源码, 可以发现。这个类上面的一行代码: This is the glue that binds the framework to the Flutter engine. 意思是WidgetsFlutterBinding类是Widget框架和Flutter engine的桥梁。 也是整个Flutter的应用层核心。WidgetsFlutterBinding继承自BindingBase, 并且with了大量的mixin类。通过 ensureInitialized()
方法我们可以得到一个全局单例的 WidgetsFlutterBinding 实例,且 mixin 的一堆 XxxBinding 也被实例化。
BindingBase 抽象类的构造方法中会调用initInstances()
方法,而各种 mixin 的 XxxBinding 实例化重点也都在各自的initInstances()
方法中,每个 XxxBinding 的职责不同,如下:
-
WidgetsFlutterBinding: Widget框架和Flutter engine的桥梁核心桥梁主体,Flutter app 全局唯一。
-
BindingBase: 绑定服务抽象类。
-
GestureBinding: 绑定手势事件。处理屏幕事件分发及事件回调处理, 初始化方法中重点是把事件处理回调
_handlePointerDataPacket
函数赋值给window的属性, 以便window收到屏幕事件后调用, window实例是Framework层与Engine层处理屏幕事件的桥梁。void initInstances() { super.initInstances(); _instance = this; window.onPointerDataPacket = _handlePointerDataPacket; } 复制代码
-
SchedulerBinding: Flutter绘制调度器相关绑定类, debug编译模式时统计绘制流程时长等操作。
-
ServicesBinding: Flutter系统平台消息监听绑定类。Platform与Flutter层通信相关服务. 同时注册监听了应用的声明周期。
-
PaintingBinding: Flutter绘制预热缓存等绑定类。重要的是, 绑定了图片缓存。
void initInstances() { super.initInstances(); _instance = this; _imageCache = createImageCache(); shaderWarmUp?.execute(); } 复制代码
-
SemanticsBinding: 语义树和Flutter引擎之间的粘合剂绑定类。
-
RendererBinding: 渲染树和Flutter引擎之间的粘合剂绑定类, 重点是持有了渲染树的根节点。
RenderView 就是 RenderObject 渲染树的根节点。
void initRenderView() { assert(!_debugIsRenderViewInitialized); assert(() { _debugIsRenderViewInitialized = true; return true; }()); renderView = RenderView(configuration: createViewConfiguration(), window: window); renderView.prepareInitialFrame(); } 复制代码
-
WidgetsBinding: Widget树和Flutter引擎之间的粘合剂绑定类。
从上面Flutter的runApp启动方法中, 可以看出, 这些XxxBinding承担的角色大致是一个桥梁关联绑定, 如下:
因为我们主要探讨Flutter启动主流程机制, 以及三棵树的诞生流程, 所以我们需要重点关注RendererBinding 和 WidgetsBinding 类的initInstances()
方法, 如下:
## RendererBinding类
/// The glue between the render tree and the Flutter engine.
渲染树(render tree) 和 Flutter engine之间的桥梁
mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, SemanticsBinding, HitTestable {
@override
void initInstances() {
super.initInstances();
_instance = this;
/*
创建管理rendering渲染管道的类, 提供接口调用来触发渲染
*/
_pipelineOwner = PipelineOwner(
onNeedVisualUpdate: ensureVisualUpdate,
onSemanticsOwnerCreated: _handleSemanticsOwnerCreated,
onSemanticsOwnerDisposed: _handleSemanticsOwnerDisposed,
);
/*
window变化相关的回调监听
*/
window
..onMetricsChanged = handleMetricsChanged
..onTextScaleFactorChanged = handleTextScaleFactorChanged
..onPlatformBrightnessChanged = handlePlatformBrightnessChanged
..onSemanticsEnabledChanged = _handleSemanticsEnabledChanged
..onSemanticsAction = _handleSemanticsAction;
/*
创建RenderView对象, 也就是RenderObject渲染树的根节点
*/
initRenderView();
......
}
/// Creates a [RenderView] object to be the root of the
/// [RenderObject] rendering tree, and initializes it so that it
/// will be rendered when the next frame is requested.
///
/// Called automatically when the binding is created.
创建渲染树的根节点对象
void initRenderView() {
......
/*
创建渲染树的根节点对象
*/
renderView = RenderView(configuration: createViewConfiguration(), window: window);
renderView.prepareInitialFrame();
}
/*
定义renderView的get方法,获取自_pipelineOwner.rootNode
*/
RenderView get renderView => _pipelineOwner.rootNode! as RenderView;
/*
定义renderView的set方法,上面initRenderView()中实例化赋值就等于给_pipelineOwner.rootNode也进行了赋值操作。
*/
set renderView(RenderView value) {
assert(value != null);
_pipelineOwner.rootNode = value;
}
## WidgetsBinding类
/// The glue between the widgets layer and the Flutter engine.
widgets 和 Flutter engine之间的桥梁
mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, RendererBinding, SemanticsBinding {
@override
void initInstances() {
super.initInstances();
_instance = this;
assert(() {
_debugAddStackFilters();
return true;
}());
/*
创建一个管理Widgets的类对象
BuildOwner类用来跟踪哪些Widget需要重建,并处理用于Widget树的其他任务,例如管理不活跃的Widget等,调试模式触发重建等。
*/
_buildOwner = BuildOwner();
/*
回调方法赋值,当第一个可构建元素被标记为脏时调用。
*/
buildOwner!.onBuildScheduled = _handleBuildScheduled;
/*
回调方法赋值,当本地配置变化或者AccessibilityFeatures变化时调用。
*/
window.onLocaleChanged = handleLocaleChanged;
window.onAccessibilityFeaturesChanged = handleAccessibilityFeaturesChanged;
SystemChannels.navigation.setMethodCallHandler(_handleNavigationInvocation);
......
}
复制代码
分析上面的初始化过程, 以及重点关注的RendererBinding、WidgetsBinding
初始化方法。我们可以知道RendererBinding 中的 RenderView 就是 RenderObject 渲染树的根节点。我们可以得到以下流程图: