- 实际挂到screen上的是elemen tree
- widget的context就是element
BuildContext get context => _element;
对于StatefulWidget,在在创建element的时候还会调用widget的createState()方法,将返回的state绑定到element。
Element class
@protected
Element inflateWidget(Widget newWidget, dynamic newSlot) {
...
final Element newChild = newWidget.createElement();
...
}
StatelessWidget流程:
- 系统调用
StatelessElement createElement() => StatelessElement(this);
- 绑定widget到element,
继承关系 Element-> ComponentElement-> StatelessElement
StatelessElement(StatelessWidget widget) : super(widget);
ComponentElement(Widget widget) : super(widget);
Element(Widget widget) : assert(widget != null), _widget = widget;
- build StatelessElement中
Widget build() => widget.build(this);
StatefulWidget流程
- StatefulWidget本身是不可变的
- 调用state的setstate()方法的时候state会将element标记为dirty.当下一次页面渲染的时候就会调用build 方法rebuild子widget
如果build返回的widget和之前的类型相同,则element和state只是更新数据,不重建,并将新的widget绑定。 - 框架在将StatefulWidget挂到tree时调用createState,这意味着如果该窗口小部件已插入到多个位置的树中,则多个State对象可能与同一StatefulWidget关联。同样,如果StatefulWidget从树中移除,后来在树再次插入时,框架将调用createState再创建一个新的State目标,简化State的生命周期。
- 如果StatefulWidget的创建者使用GlobalKey作为其 键,则StatefulWidget在从树中的一个位置移动到另一个位置时保持相同的State对象
- 系统调用
StatefulElement createElement() => StatefulElement(this);
- 绑定widget和state到element,同时widget也会被绑定到state
继承关系 Element-> ComponentElement-> StatelessElement
StatefulElement(StatefulWidget widget) : _state = widget.createState(), super(widget) {..._state._widget = widget;...}
ComponentElement(Widget widget) : super(widget);
Element(Widget widget) : assert(widget != null),_widget = widget;
- build StatefulElement中
Widget build() => state.build(this);
性能优化
- 不要整体更新,只更新需要更新的widget
- 嵌套层级尽量低
- 如果widget子树没更新,应该重用,可在state中用Widget child保存
- 将Widget标志为const,这相当于缓存窗口小部件并重新使用它。
- 避免更改子树深度和Widget类型
- 使用GlobalKey
- 使用RepaintBoundary和RelayoutBoundary优化性能
rebuild流程
- BuildOwner的buildScope方法被调用
void buildScope(Element context, [ VoidCallback callback ]) {
···
while (index < dirtyCount) {
···
_dirtyElements[index].rebuild();
···
}
···
}
- Element 的performRebuild方法
void rebuild() {
...
performRebuild();
...
assert(!_dirty);
}
- ComponentElement的build方法
void performRebuild() {
//该方法中会调用build()方法
}
- StatelessElement和StatefulElement
build()
方法
//stateless
Widget build() => widget.build(this);
//stateful
Widget build() => state.build(this);