Element主要分为2类
- ComponentElement: 合成其它的Element, 它的子类又StatelessElement,StatefulElement,ProxyElement, 其中StatelessElement和StatefulElement主要用于组建有状态和无状态的widget,ProxyElement则是用于更新依赖,传递数据,局部状态管理。
- RenderObjectElement
提供RenderObject的配置信息,用于创建对应结点的RenderObject
Element家族图普
DiagnosticableTree (diagnostics.dart)
Element (framework.dart)
ComponentElement (framework.dart)
StatelessElement (framework.dart)
StatefulElement (framework.dart)
ProxyElement (framework.dart)
InheritedElement (framework.dart)
ParentDataElement (framework.dart)
RenderObjectElement (framework.dart)
SliverMultiBoxAdaptorElement (sliver.dart)
_SliverPrototypeExtentListElement (sliver_prototype_extent_list.dart)
_TableElement (table.dart)
_LayoutBuilderElement (layout_builder.dart)
ListWheelElement (list_wheel_scroll_view.dart)
_SliverPersistentHeaderElement (sliver_persistent_header.dart)
_CupertinoAlertRenderElement (action_sheet.dart)
_CupertinoDialogRenderElement (dialog.dart)
_RenderDecorationElement (input_decorator.dart)
_ListTileElement (list_tile.dart)
_RenderChipElement (chip.dart)
SingleChildRenderObjectElement (framework.dart)
_OffstageElement (basic.dart)
_SliverOffstageElement (sliver.dart)
MultiChildRenderObjectElement (framework.dart)
_ViewportElement (viewport.dart)
_TheatreElement (overlay.dart)
_TextSelectionToolbarItemsElement (text_selection.dart)
LeafRenderObjectElement (framework.dart)
RootRenderObjectElement (framework.dart)
RenderObjectToWidgetElement (binding.dart)
Element {
- 继承于BuildContext, 同时和Widget绑定
Element > DiagnosticableTree > BuildContext
Element(Widget widget)
StatelessElement createElement() => StatelessElement(this);
-
slot
描述了Element
在Tree的位置,在BuilderOwner装配的时候回根据slot决定Element在tree中的位置
//提供给parentElement,用于确定他在child list中的位置
dynamic get slot => _slot;
int get depth => _depth;
set slot => _slot;
static int _sort(Element a, Element b) {
if (a.depth < b.depth)
return -1;
if (b.depth < a.depth)
return 1;
if (b.dirty && !a.dirty)
return -1;
if (a.dirty && !b.dirty)
return 1;
return 0;
}
void mount(Element parent, dynamic newSlot)
- 通过BuilderOwner可以对ElementTree中的元素更新
BuildOwner get owner => _owner;
...
void reassemble() {
markNeedsBuild();
visitChildren((Element child) {
child.reassemble();
});
}
- 获取当前Element下对应的RenderObject(最近的一个RenderObject)
class Element
...
RenderObject get renderObject {
RenderObject result;
void visit(Element element) {
assert(result == null); // this verifies that there's only one child
if (element is RenderObjectElement)
result = element.renderObject;
else
element.visitChildren(visit);
}
visit(this);
return result;
}
abstract class ComponentElement extends Element
...
@override
void visitChildren(ElementVisitor visitor) {
if (_child != null)
visitor(_child);
}
- 管理Child RenderObject,
void detachRenderObject() {
visitChildren((Element child) {
child.detachRenderObject();
});
_slot = null;
}
//Add [renderObject] to the render tree at the location specified by [slot].
void attachRenderObject(dynamic newSlot) {
assert(_slot == null);
visitChildren((Element child) {
child.attachRenderObject(newSlot);
});
_slot = newSlot;
}
- Globalkey绑定,缓存带有GlobalKey的Element
void mount(Element parent, dynamic newSlot)
......
if (key is GlobalKey) {
key._register(this);
}
void unmount() {
...
if (key is GlobalKey) {
key._unregister(this);
}
...
}
- Global Key
Element inflateWidget(Widget newWidget, dynamic newSlot) {
assert(newWidget != null);
final Key key = newWidget.key;
if (key is GlobalKey) {
final Element newChild = _retakeInactiveElement(key, newWidget);
...
}
final Element newChild = newWidget.createElement();
...
}
总结
- Element类似是一个装配容器,他同时持有了
BuilderOwner
和Widget
,BuilderOwner指令触发Element树的构建,在构建过程中它回读取Widget
的配置信息,生成在Element树中的节点,同时也提供了也控制着对应的RenderObjet的绑定操作。 - BuilderOwner(TimeSync) -> Element(Widget)Tree -> RenderObject -> RenderTree
BuildContext
- 用于定位widget在widget tree中的位置,
- 通过widge树的层级关系,生成一个对应位置的Element树,具体可以参照 Element类中更新
slot
和depth
的相关方法 - 相关属性介绍:
//当前Context的配置信息
Widget get widget;
//当前Context的builderOwner,用于管理当前Context的渲染管道
BuildOwner get owner;
//用于查找当前关联的widget的 renderObject,如果找不到就找到下一级最近的
RenderObject findRenderObject();
//通过findRenderObject查找到的RenderObject在窗口中的大小
Size get size;
//注册当前的buildContext到它的上一级的BuildContext中,当`anccestor`的widget变化时会触发当前这个buildContext rebuilt方法
//返回值 InheritedWidget是ancestor.widget
InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object aspect });
//返回当前Context最近的一个`InheritedWidget`
T dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({ Object aspect });
ComponentElement
- 组成其他的Eleemnt元素
- 在
mount
和performRebuild
方法中构建新的Widget,并生成_child element
StatelessElement
- 主要重写了
build
和update
方法,widget更新检测, - build时将当前的BuildContext传递给widget
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);
assert(widget == newWidget);
_dirty = true;
rebuild();
}
}
StatefulElement
- 它是一个包含StatefulWidget配置信息的Element
- 它比
StatelessElement
中多了一个State,在reassemble
,_firstBuild
,performRebuild
,activate
,deactivate
,unmount
中进行依赖更新
class StatefulElement extends ComponentElement {
//根据给定的StatefulWidget配置信息创建Element
StatefulElement(StatefulWidget widget)
: _state = widget.createState(),
_state._widget = widget;
...
//构建对应state状态的widget
@override
Widget build() => _state.build(this);
@override
void reassemble() {
state.reassemble(); //state重建
super.reassemble();
}
@override
void _firstBuild() {
_state.didChangeDependencies();
super._firstBuild();
}
@override
void performRebuild() {
if (_didChangeDependencies) {
_state.didChangeDependencies();
_didChangeDependencies = false;
}
super.performRebuild();
}
@override
void update(StatefulWidget newWidget) {
super.update(newWidget);
final StatefulWidget oldWidget = _state._widget;
...
rebuild();
}
@override
void activate() {
super.activate();
assert(_active); // otherwise markNeedsBuild is a no-op
markNeedsBuild();
}
@override
void deactivate() {
_state.deactivate();
super.deactivate();
}
//Element移除时,释放state资源
@override
void unmount() {
super.unmount();
_state.dispose();
_state._element = null;
_state = null;
}
@override
InheritedWidget inheritFromElement(Element ancestor, { Object aspect }) {
return dependOnInheritedElement(ancestor, aspect: aspect);
}
@override
InheritedWidget dependOnInheritedElement(Element ancestor, { Object aspect }) {
...
return super.dependOnInheritedElement(ancestor as InheritedElement, aspect: aspect);
}
//依赖更新
@override
void didChangeDependencies() {
super.didChangeDependencies();
_didChangeDependencies = true;
}
}
ProxyElement
- 相比较StatelessElement,多了一个notifyClients方法,
abstract class ProxyElement extends ComponentElement
...
void update(ProxyWidget newWidget) {
final ProxyWidget oldWidget = widget;
..
updated(oldWidget);
...
rebuild();
}
void updated(covariant ProxyWidget oldWidget) {
notifyClients(oldWidget);
}
ParentDataElement
区别在于如果是ParentDataElement
会调用所有的child._updateParentData
所有的child都能更新
class ParentDataElement<T extends ParentData> extends ProxyElement {
...
void notifyClients(ParentDataWidget<T> oldWidget) {
_applyParentData(widget);
}
...
void _applyParentData(ParentDataWidget<T> widget) {
void applyParentDataToChild(Element child) {
if (child is RenderObjectElement) {
child._updateParentData(widget);
} else {
assert(child is! ParentDataElement<ParentData>);
child.visitChildren(applyParentDataToChild);
}
}
visitChildren(applyParentDataToChild);
}
InheritedElement
- 一个使用InheriteWidget作为它的配置信息的Element
- 初始化
class InheritedElement extends ProxyElement {
/// Creates an element that uses the given widget as its configuration.
InheritedElement(InheritedWidget widget) : super(widget);
- 内部持有一个
Map<Element, Object>
的_dependents
,用于缓存对应Element的依赖数据
Map<Element, Object> _dependents = HashMap<Element, Object>();
...
@protected
Object getDependencies(Element dependent) {
return _dependents[dependent];
}
@protected
void setDependencies(Element dependent, Object value) {
_dependents[dependent] = value;
}
@protected
void updateDependencies(Element dependent, Object aspect) {
setDependencies(dependent, null);
}
@protected
void notifyDependent(covariant InheritedWidget oldWidget, Element dependent) {
dependent.didChangeDependencies();
}
@override
void updated(InheritedWidget oldWidget) {
if (widget.updateShouldNotify(oldWidget))
super.updated(oldWidget);
}
@override
void notifyClients(InheritedWidget oldWidget) {
...
notifyDependent(oldWidget, dependent);
}
}
update widget -> notifiyClients -> notifyDependent -> didChangeDependencies
- 缓存所有InheritedElement,会将父类的
_inheritedWidget
一起拿过来
@override
void _updateInheritance() {
assert(_active);
final Map<Type, InheritedElement> incomingWidgets = _parent?._inheritedWidgets;
if (incomingWidgets != null)
_inheritedWidgets = HashMap<Type, InheritedElement>.from(incomingWidgets);
else
_inheritedWidgets = HashMap<Type, InheritedElement>();
_inheritedWidgets[widget.runtimeType] = this;
}
RenderObjectElement
- 一个使用RenderObjectWidget作为配置信息的Element在Element装配的时候会创建RenderObject
- 同时会将RenderObjet放入到指定的slot中,生成RenderTree
void mount(Element parent, dynamic newSlot) {
super.mount(parent, newSlot);
...
_renderObject = widget.createRenderObject(this);
attachRenderObject(newSlot);
...
- 主要api解析
//通过递归调用 `ancestor._parent`(Element中_parent)来获取anestor `RenderObjectElemenet`
RenderObjectElement _findAncestorRenderObjectElement() {
Element ancestor = _parent;
while (ancestor != null && ancestor is! RenderObjectElement)
ancestor = ancestor._parent;
return ancestor as RenderObjectElement;
}
//同上,递归调用获取anccestor为`ParenetDataElement<ParentData>`的Element
ParentDataElement<ParentData> _findAncestorParentDataElement()
mount(Element parent, dynamic newSlot)
unmount()
update(covariant RenderObjectWidget newWidget)
_updateSlot(dynamic newSlot)
performRebuild
//用于MultiRenderObject来更新数据
List<Element> updateChildren(List<Element> oldChildren, List<Widget> newWidgets, { Set<Element> forgottenChildren })
attachRenderObject(dynamic newSlot)
_updateParentData
RootRenderObjectElement>RenderObjectElement
- 指定一个BuilderOwner,用于管理ElementTree,RenderTree
RootRenderObjectElement(RenderObjectWidget widget) : super(widget);
mount(Element parent, dynamic newSlot)
LeafRenderObjectElement>RenderObjectElement
- 无法进行增删改,在RenderTree的末端
forgetChild(Element child)
insertChildRenderObject(RenderObject child, dynamic slot)
moveChildRenderObject(RenderObject child, dynamic slot)
removeChildRenderObject(RenderObject child)
SingleChildRenderObjectElement > RenderObjectElement
- 只有一个RenderObject的Element,无法移动RenderObject层级,因为当前层级只有它一个
visitChildren(ElementVisitor visitor)
forgetChild(Element child)
mount(Element parent, dynamic newSlot)
update(SingleChildRenderObjectWidget newWidget)
insertChildRenderObject(RenderObject child, dynamic slot)
//无法移动
void moveChildRenderObject(RenderObject child, dynamic slot) {
assert(false);
}
removeChildRenderObject(RenderObject child)
MultiChildRenderObjectElement > RenderObjectElement
- 一个使用MultiChildRenderObjectWidget配置的Element
- 主要用于管理它的child renderObject在 renderTree中的位置
MultiChildRenderObjectWidget get widget => super.widget as MultiChildRenderObjectWidget;
Iterable<Element> get children => _children.where((Element child) => !_forgottenChildren.contains(child));
insertChildRenderObject(RenderObject child, IndexedSlot<Element> slot)
moveChildRenderObject(RenderObject child, IndexedSlot<Element> slot)
removeChildRenderObject(RenderObject child)
visitChildren(ElementVisitor visitor)
forgetChild(Element child)
mount(Element parent, dynamic newSlot)
update(MultiChildRenderObjectWidget newWidget)
网友评论