- 实际挂到screen上的是elemen tree
- widget的context就是element
BuildContext get context => _element;
对于StatefulWidget,在在创建element的时候还会调用widget的createState()方法,将返回的state绑定到element。
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类型,例如:可以使用IgnorePointer的ignoring属性控制
- 使用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);
Key
局部key只会比较树中相同位置的widget,如children中index 为1的element不会复用到index为0的element位置,如果是children从后面添加元素,则前面的element可以复用。如果父element被重建,则子element一定也会被重建
StatelessWidget 如果canUpdate,会调用widget的build方法。
当新的widget并挂到树上时,会调用canUpdate方法,方法中有对key的比较
@immutable
abstract class Widget extends DiagnosticableTree {
const Widget({ this.key });
final Key key;
···
static bool canUpdate(Widget oldWidget, Widget newWidget) {
return oldWidget.runtimeType == newWidget.runtimeType
&& oldWidget.key == newWidget.key;
}
}









网友评论