Widget 的简介
先看一下Widget. 从 Flutter的注释来看, 官方对Widget的解释是:Describes the configuration for an [Element], 对于Flutter Framework来说, 并且是一个immutable description , 在后续会关联到Element.
Widget - Element - RenderObject 三棵树的内容后面会整理
有三个重点需要:
Widget 是一个不可变的配置信息
Widget 会关联Element类型
抽象类, 实际在开发时会继承子类: StatefulWidget, StatelessWidget.
StatefulWidget的可变状态完全依赖于关联的State
abstract class Widget extends DiagnosticableTree {
const Widget({ this.key });
final Key key;
@protected
Element createElement();
...
/// Whether the newWidget
can be used to update an [Element] that currently
/// has the oldWidget
as its configuration.
static bool canUpdate(Widget oldWidget, Widget newWidget) {
return oldWidget.runtimeType == newWidget.runtimeType
&& oldWidget.key == newWidget.key;
}
}
复制代码
StatelessWidget的生命周期
StatelessWidget作为无状态的Widget, 生命周期比较简单:
const StatelessWidget({ Key? key }) : super(key: key); 构造函数
StatelessElement createElement() => StatelessElement(this); Widget关联的Element,
Widget build(BuildContext context); 说明The framework calls this method when this widget is inserted into the tree
//Element 内部会只有 widget
/// An [Element] that uses a [StatelessWidget] as its configuration.
class StatelessElement extends ComponentElement {
/// Creates an element that uses the given widget as its configuration.
StatelessElement(StatelessWidget widget) : super(widget);
/// 使用
@override
StatelessWidget get widget => super.widget as StatelessWidget;
@override
Widget build() => widget.build(this);
@override
void update(StatelessWidget newWidget) {
super.update(newWidget);
_dirty = true;
rebuild();
}
}
复制代码
StatefulWidget的生命周期
StatefulWidget是有状态的Widget, 与之关联的State的生命周期如下:
widget: const StatefulWidget({ Key? key }) : super(key: key);
widget: StatefulElement createElement() => StatefulElement(this);
widget: State createState()
state: constructor
state: initState
state: didChangeDependencies (若InheritedWidget.rebuild => child.didChangeDependencies)
state: Widget build(BuildContext context); (setState() => didUpdateWidget => build)
state: 将Widget - Element加入tree中
state: deactivate
state: dispose
将Element移除true
InheritedWidget 方法 rebuild 时, 会调用childNode 中的 didChangeDependencies
setState() 方法时, 会调用didUpdateWidget 方法, 然后调用build
以上过程中几个关键的内容:
在StatefulWidget在调用createElement()方法时, 关键的内容:
// StatefulWidget 中在 Widget被 mount 到 tree 时调用
StatefulElement createElement() {
// Element 的构造函数
return StatefulElement(this);
}
/// Creates an element that uses the given widget as its configuration.
/// Element构造函数中
/// 1. 会主动调用 widget.createState()方法, 并创建 _state!!!
/// 2. 然后, 在state中持有 element 和 widget
StatefulElement(StatefulWidget widget): _state = widget.createState(), super(widget) {
...
state._element = this;
state._widget = widget;
}
复制代码
在createState()时, 可能会调用多次. For example, if the widget is inserted into the tree in multiple locations, the framework will create a separate [State] object for each location
SetState的实现与dirty Element的标记与更新:
/// State 中的方法
void setState(VoidCallback fn) {
// 先调用 fn() ...
final Object? result = fn() as dynamic;
_element!.markNeedsBuild();
}
/// Element 中的方法
/// Marks the element as dirty and adds it to the global list of widgets to
/// rebuild in the next frame.
///
/// Since it is inefficient to build an element twice in one frame,
/// applications and widgets should be structured so as to only mark
/// widgets dirty during event handlers before the frame begins, not during
/// the build itself.
void markNeedsBuild() {
...
_dirty = true; // 仅仅标记 Element, 会加入到全局 dirty list 中, 下一帧循环时, 会更新
owner!.scheduleBuildFor(this); // owner 是在调用 mount 时, 传入的parent.owner设置的
}
// BuildOwner 类 -- Framework 中的管理类
/// Adds an element to the dirty elements list so that it will be rebuilt
/// when [WidgetsBinding.drawFrame] calls [buildScope].
void scheduleBuildFor(Element element) {
...
_dirtyElements.add(element); // 将 element 添加到全局的 dirty list 中
element._inDirtyList = true;
}
网友评论