启动流程
void runApp(Widget app) {
WidgetsFlutterBinding.ensureInitialized()
..scheduleAttachRootWidget(app)
..scheduleWarmUpFrame();
}
整体流程
1、创建根Element
RenderObjectToWidgetElement
为整个页面的根Element。
继承关系:RenderObjectToWidgetElement—>RootRenderObjectElement—>RenderObjectElement—>Element
- RenderObjectToWidgetAdapter–>RenderWidget–>Widget
- RenderObjectToWidgetElement
使用RenderObjectToWidgetAdapter创建RenderObjectToWidgetElement对象。
在创建RenderObjectToWidgetAdapter时,传入的RenderView和根Widget,根Widget作为RenderObjectToWidgetAdapter的child。
RenderObjectToWidgetAdapter是RenderObjectWidget子类。
2、执行根Element挂载
挂载时,根Widget是StatelessWidget或StatefullWidget,会进行子元素挂载,创建Widget树、Element树和RenderObject树
如何创建RenderObject树的?
3、请求VSYN信号
在应用启动过程有两处请求VSYNC信号的调用,分别在attachRootWidget时,及之后。
- scheduleWarmUpFrame()
- SchedulerBinding.instance.ensureVisualUpdate()
State
- initState()
- didUpdateWidget()
- reassemble
- setState
- deactivate()
- activate()
- dispose()
- build()
- didChangeDependencies()
Element
- mount()
- unmount()
- update()
- updateChild()
- updateSoltForChild()
- attachRenderObject()
- inflateWidget()
- activate()
- deactivate()
- markNeedsBuild()
- performRebuild()
- rebuild()
相关文件
- lib/src/widgets/binding.dart
- lib/src/widgets/framework.dart
//lib/src/widgets/binding.dart
void runApp(Widget app){
WidgetsFlutterBinding.ensureInitialized()
//创建根Element并执行挂载操作
..scheduleAttachRootWidget(app)
//触发请求VSYNC信息
..scheduleWarmUpFrame();
}
//WidgetsBinding
void scheduleAttachRootWidget(Widget rootWidget){
attachRootWidget(rootWidget);
}
//RenderObjectToWidgetApater extends RenderObjectWidget
void attachRootWidget(Widget rootWidget){
//构建RenderObjectToWidgetObject对象时,将rootWidget赋值给了它的child字段
_renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(
container: renderView,
child: rootWidget,
).attachToRenderTree(buildOwner, renderViewElement as RenderObjectToWidgetElement<RenderBox>);
//触发请求VSYNC信息
SchedulerBinding.ensureVisualUpdate();
}
//RenderObjectToWidgetAdapter
RenderObjectToWidgetElement<T> attachToRenderTree(BuildOwner owner, [ RenderObjectToWidgetElement<T> element]){
//在上述调用中,element=null
if(element == null){
owner.lockState((){
element = createElement();
element.assignOwner(owner);
});
owner.buildScope(element, (){
//此时element已经有child, 在createElement已经将widget传递过去
element.mount(null,null);
});
}else{
}
}
//RenderObjectToWidgetAdapter
RenderObjectToWidgetElement<T> createElement(){
return RenderObjectToWidgetElement<T>(this);
}
//RenderObjectToWidgetElement extends RootRenderObjectElement extends RenderObjectElement
//RenderObjectToWidgetElement
void mount(Element parent, Object? newSolt){
super.mount(parent, newSolt);
_rebuild();
}
void _rebuild(){
//触发widget创建widget
_child = updateChild(_child, wiget.child, _rootChildSolt);
}
RenderObjectElement在mount时,会通过widget创建RenderObject对象。
//lib/src/widgets/framework.dart
//RenderObjectElement
void mount(){
_renderObject = (widget as RenderObjectWidget).createRenderObject(this);
attachRenderObject(newSolt);
super.performRebuild();//基类标记为_dirty
}
挂载流程
RenderObjectElement在mount时会创建RenderObject对象。
Element.mount(Element parent,)
ComponentElement._firstBuild();
Element.rebuild();
ComponentElement.performBuild();
build()
StatelessElement.build(BuildContext context);
StatefulElement.build(BuildContext context);
ComponentElement.updateChild(Element child, Widget newWidget, Object newSolt){
}
//lib/src/widgets/framework.dart Element
//Element类
Element inflateWidget(Widget newWidget, Ojbect? newSolt){
if(key is BlobalKey){
Element newChild = _retakeInactiveElement(key, newWeiget);
if(newChild != null){
newChild._activieWidthParent(this, newSolt);
Element? updateChild = updateChild(newChild, newWidget, newSolt);
return updateChild;
}
}
Element newChild = newWidget.createElement();
newChild.mount(this, newSolt);
return newChild;
}
//更新child
Element updateChild(Element child, Widget newWidget, Object newSolt) {
if(newWidget == null){
if(child != null) {
deactivateChild(child);
}
return null;
}
Element newChild;
if(child != null){
bool hasSameSuperclass = true;
if(hasSameSuperclass && child.widget == newWidget){
if(child.solt != newSolt){
updateSoltForChild(child, newSolt);
}
newChild = child;
} else if(hasSameSuperclass && Widget.canUpdate(child.widget, newWidget)){
if(child.solt != newSolt){
updateSoltForChild(newSolt);
}
child.update(newWidget);
newChild = child;
} else {
deactivateChild(child);
newChild = inflateWidget(newWidget, newSolt);
}
} else {
newChild = inflateWidget(newWidget, newSolt);
}
}
渲染流程
请求VSYN信息
核心方法:scheduleFrame()
请VSYNC信息触发场景
- 调度器触发,如定时器、动画、滚动等
- 页面启动、窗口变化等
- 用户主动解决,setState
以setState为例
- State.setState()
- Element.markNeedsBuild()
- BuildOwner.scheduleBuildFor(element);
- onBuildScheduled();
- WidgetsBinding._handleBuildScheduled();
- SchedulerBinding.ensureVisualUpdate()
- PlatformDispatcher.scheduleFrame()
------------------ 以下为C++ ------------------
- PlatformConfigurationNaitveApi::scheduleFrame()
- RuntimeController::ScheduleFrame();
- Engine:ScheduleFrame();
- Animator::RequestFrame();
- Animator::AwaitVsync()
- VsyncWaiter::AwaitVsync()
回调VSYNC
核心方法:BeginFrame()
请求SYNC信号后,由系统触发回调
- Animator::BeginFrame();
- Shell::OnAnimatorBeginFrame();
- Engine::BeginFrame();
- RuntimeController::BeginFrame();
- PltformConfiguration::BeginFrame(),反射调用_beginFrame&_drawFrame
------------------ 以下为Dart ------------------
- _beginFrame(flutter/lib/ui/hooks.dart)
- PlatformDispatcher._beginFrame();
- SchedulerBinding._handleBeginFrame();(在SchedulerBinding.ensureFrameCallbacksRegistered方法中建立绑定关系)
- SchedulerBinding._handleDrawFrame();
// src/lib/rendering/binding.dart
//RendererBinding
void drawFrame() {
pipelineOwner.flushLayout();
pipelineOwner.flushCompositingBits();
pipelineOwner.flushPaint();
//进行layer合并,并将layerTree传递到C++进行渲染
renderView.compositeFrame();
}
布局Layout
// src/lib/rendering/object.dart
//PipelineOwner
void flushLayout() {
for( int i=0; i<dirtyNodes.length; i++){
node._layoutWidthoutResize();
}
}
//RenderObject
void _layoutWithoutResize(){
performLayout();
markNeedPaint();
}
//RenderView extends RenderObject
void performLayout(){
if(child != null) {
child.layout(BoxConstraints.tight(_size));
}
}
//RenderBox extends RenderObject, 布局类RenderObject均继承RenderBox
void layout(Constraints constraints, {bool parentUsesSize = false}) {
super.layout(constraints, parentUsesSize);
}
//RenderObject
void layout(Constraints constraints, { bool parentUsesSize = false }) {
visitChildren();
performLayout();
markNeedsPaint();
}
//RenderObject
void markNeedsPaint(){
if(isRepaintBoundary && _wasRepaintBoundary){
pipelineOwner._nodesNeedingPaint.add(this);
pipelineOwner.requestVisubleUpdate();
} else if(parent is RenderObject){
//parent哪来的?
RenderObject parent = this.parent as RenderObject;
parent.markNeedsPaint();
} else {
pipelineOwner.requestVisualUpdate();
}
}
绘制Paint
//lib/src/rendering/object.dart
//PipelineOwner
void flushPaint() {
for(RenderObject node in dirtyNodes..sort((RenderObject a, RenderObject b) => b.depth - a.depth)){
if(node._needsPaint)
PaintingContext.repaintCompositedChild(node);
else
PaintingContext.updateLayerProperties(node);
}
}
----Render----
BindingBase.reassembleApplication();
RendererBinding.performReassemble();
RenderView.reassemble();
RenderObject.reassemble()
RenderObject.markNeedsPaint()
ower.requestVisualUpdate()(PipelineOwner)
RendererBinding 创建了 PipelineOwner,将ensureVisualUpdate赋值给onNeedVisualUpdate字段
----Widget-----
BuildOwner.reassemble();
Element.reassemble();
.markNeedsBuild();
获取Surface
获取Canvas
WidgetsBinding.drawFrame()
BuildOwner.buildScope()
PipelineOwner.flushLayout();
RenderObject._layoutWithoutResize();
RenderObject.performLayout()(RenderView)
RenderBox.layout(BoxConstraints.tight(_size));
RenderObejct.performLayout();
PipelineOwner.flushPaint();
RenderView.paint(PaintingContext context, Offset offset);
PaintingContext.paintChild();
RenderObject._paintWithContext();
RenderObject.paint()
自定义View
因为有Widget、Element、RenderObject3棵树,自定个View比较复杂
提前创建好了一个CustomPaint的Widget,有一个painter参数,暴露给用户来自定View样式。
painter类型CustomPainter
图像数据送显
RenderView.compositeFrame();
final ui.SceneBuilder builder = ui.SceneBuilder();
final ui.Scene scene = layer!.buildScene(builder);
_window.render(scene);
scene.dispose();
attachRootWidget()
更新
MyHomePageState extends State
State.setState();
Element.markNeedsBuild();
BuildOwner.scheduleBuildFor(element);
onBuildScheduled();
BuildOwner.onBuildScheduled()回调方法绑定发生在WidgetsBinding类,
WidgetsBinding._handleBuildScheduled();
ensureVisualUpdate,ensureVisualUpdate方法属于SchedulerBinding类,由WidgetsBinding 通过on 混入
scheduleFrame()
PlatformDispatcher.scheduleFrame()
_scheduleFrame(),由@FfiNative注解
@FfiNative()>(‘PlatformConfigNativeApi::ScheduleFrame’)
external static void _scheduleFrame();
Element挂载
Element.mount()
关联parent,设置solt、owner,并注册key。
关联parent时为何没有设置parent->child=this?
原因:parent.updateChild创建子Element时已经关联。
void mount(Element parent, Object newSolt){
_parent = parent;
_solt = newSolt;
if(parent != null){
_owner = parent.owner;
}
final Key key = widget.key;
if(key is GlobalKey){
_owner._registerGlobalKey(key, this);
}
}
void rebuild({force = false}){
performRebuild();
}
void performRebuild(){
_dirty = false;
}
ComponentElement.mount()
自定的Widget要么继承StatelessWidget,要么继承StatefulWidget,它们均又继承自ComponentElement。
ComponentElement.mount()时,会触发重新rebuild()。
void mount(Element parent, Object newSolt){
super.mount(parent, newSolt);
_firstBuild();
}
void _firstBuild(){
rebuild();
}
void performRebuild(){
Widget built = build();
super.performRebuild();
_child = updateChild(_child, built, solt);
}
RenderObjectElement.mount()
RenderObjectElement在挂载时,会创建RenderObject,
void mount(Element parent, Object newSolt){
super.mount(parent, newSolt);
_renderObject = (widget as RenderObjectWidget).createRenderObject(this);
attachRenderObject(newSolt);
// clears the "dirty" flag
super.performRebuild();
}
void performRebuild(){
_performRebuild();
}
void _performRebuild(){
//将Widget中的属性更新到RenderObject。更新RenderObject时,如果属性有变化,则将RenderObject添加到dirtyList中,重新渲染
(widget as RenderObjectWidget).updateRenderObject(this, renderObject);
//清除Element _dirty标记,也就是说Element在属性更新过程中的使命已经完成,接下来的操作交给RenderObject处理就可以了。
super.performRebuild();
}
RenderObject挂载
RenderObject挂载在Element中完成。
// RenderObjectElement
void attachRenderObject(Object newSolt){
_solt = newSolt;
_ancestorRenderObjectElement = _findAncestorRenderObjectElement();
_ancestorRenderObjectElement.insertRenderObjectElementChild(renderObject, newSolt);
}
// SingleChildRenderObjectElement
void insertRenderObjectElement(RenderObject child, Object solt){
final RenderObjectWithChildMixin<RenderObject> renderObject = this.renderObject as RenderObjectWidthChildMixin<RenderObject>;
renderObject.child = child;
}
// MultiChildRenderObjectElement
void insertRenderObjectElement(RenderObject child, Object solt){
final ContainerRenderObjectMixin<RenderObject, ContainerParentDataMixin<RenderObject>> renderObject = this.renderObject;
renderObject.insert(child, after: solt.value?.renderObject);
}
rebuild
页面元素创建完毕,由点击等触发setState调用,从而触发Element.rebuild发生。
rebuild会调用performRebuild方法。
继承ComponentElement的元素(组合Element),会调用Widget/State的build()方法,重新创建一个Widget对象,来更新当前Element的child,或更新当前child.widget(Widget的build方法就是用来创建子Widget的)。
继承RenderObjectElement的元素(渲染Element),会调用RenderObjectWidget.updateRenderObject()将Widget的属性信息同步到RenderObject。同步过程,如果发现属性值有变化,则会调用RenderObject.markNeedsPaint()方法,标记当前RenderObject为脏元素,需要刷新。在VSYNC信号到来时,即可取得脏元素进行重新绘制。
//Element
void rebuild(){
performRebuild();
}
//ComponentElement
void rebuild(){
Widget built = build();
_child = updateChild(_child, build, solt);
}
//Element
Element updateChild(Element child, Widget newWidget, Object newSolt) {
//xxxx
child.update(newWidget);
//xxxx
}
update
//StatelessElement
void update(StatelessWidget newWidget){
super.update(newWidget);
rebuild({force:true});
}
//StatefulElement
void update(StatefulWidget newWidget){
super.update(newWidget);
StatefulWidget oldWidget = state._widget;
state._widget = newWidget;
state.didUpdateWidget(oldWidget);
rebuild({force:true});
}
//SingleChildRenderObjectElement
void update(SingleChildRenderObjectWidget newWidget){
super.update(newWidget);
_child = updateChild(_child, (newWidget as SingleChildRenderObjectWidget).child, null);
}
//MultiChildRenderObjectElement
void update(MultiChildRenderObjectWidget newWidget){
super.update(newWidget);
MultiChildRenderObjectWidget multiChildRenderObjectWidget = widget as MultiChildRenderObjectWidget;
_children = updateChildren(_children, multiChildRenderObjectWidget.children, forgottenChildren: _forgottenChildren);
_forgottenChildren.clear();
}
Switch控件的RenderObject在更新属性时,将自己标记为_dirty。
//lib/src/cupertino/switch.dart
set activeColor(Color value) {
assert(value != null);
if (value == _activeColor) {
return;
}
_activeColor = value;
markNeedsPaint();
}