RenderObjectWidget
是Widget
例如SizeBox
,Column
等
RenderObjectElement
是这类Widget
生成的Element
类型,
例如SizeBox
对应SingleChildRenderObjectElement
(单子节点的Element
)
RenderObject
才是真正负责绘制的对象,其中包含了paint
,layout
等方法~
Text
组件为例:
class Text extends StatelessWidget
Text
build返回的是
class RichText extends MultiChildRenderObjectWidget
MultiChildRenderObjectWidget
- > MultiChildRenderObjectElement
abstract class MultiChildRenderObjectWidget extends RenderObjectWidget {
MultiChildRenderObjectElement createElement() => MultiChildRenderObjectElement(this);
创建关系:
abstract class RenderObjectWidget extends Widget
@override
@factory
RenderObjectElement createElement();
@protected
@factory
RenderObject createRenderObject(BuildContext context);
RenderObjectElement
会重写mount
abstract class RenderObjectElement extends Element
...
void mount(Element? parent, Object? newSlot) {
super.mount(parent, newSlot);
_renderObject = widget.createRenderObject(this);
attachRenderObject(newSlot);
_dirty = false;
}
void attachRenderObject(Object? newSlot) {
_slot = newSlot;
//查找上一个RenderObjectElement
_ancestorRenderObjectElement = _findAncestorRenderObjectElement();
//上一个RenderObjectElement插入当前的renderObject
_ancestorRenderObjectElement?.insertRenderObjectChild(renderObject, newSlot);
...
遍历_parent
(就是上个节点的element
,这个_parent
在每次的mount
方法设置),一直遍历知道找到最近的一个RenderObjectElement
RenderObjectElement? _findAncestorRenderObjectElement() {
Element? ancestor = _parent;
while (ancestor != null && ancestor is! RenderObjectElement)
ancestor = ancestor._parent;
return ancestor as RenderObjectElement?;
}
在回顾下inflateWidget
Element inflateWidget(Widget newWidget, Object? newSlot) {
//this为A newWidget则是B,通过Bwidget 创建对应的element
final Element newChild = newWidget.createElement();
//新生成的element插入element树中
newChild.mount(this, newSlot);
return newChild;
}
SingleChildRenderObjectElement
@override
void insertRenderObjectChild(RenderObject child, Object? slot) {
renderObject = this.renderObject;
renderObject.child = child;
}
MultiChildRenderObjectElement
void insertRenderObjectChild(RenderObject child, IndexedSlot<Element?> slot) {
renderObject = this.renderObject;
renderObject.insert(child, after: slot.value?.renderObject);
}
总结:
inflateWidget
会触发RenderObjectWidget
的createElement
创建RenderObjectElement
,
再调用RenderObjectElement
的mount
方法
mount
方法调用RenderObjectWidget
的createRenderObject
方法创建RenderObject
然后找到最近的一个父RenderObjectElement
调用insertRenderObjectChild
插入RenderObject
(注意:这里不是RenderObjectElement
的child
,而是RenderObjectElement
关联的RenderObject
的child
, element
树里面都是element
, RenderObject
树里面都是RenderObject
)
MultiChildRenderObjectElement
多子节点挂载逻辑
void insertRenderObjectChild(RenderObject child, IndexedSlot<Element?> slot) {
renderObject = this.renderObject;
renderObject.insert(child, after: slot.value?.renderObject);
}
void insert(ChildType child, { ChildType? after }) {
adoptChild(child);
_insertIntoChildList(child, after: after);
}
多节点添加子节点逻辑
每个子节点的parentData
的after
用来指向前一个子节点 previous
指向下一个子节点
-
Father
有子节点s1 s2 s3
s2
的parentData
的previous
会用来指向s1
,s1
的next
会指向s2
以此类推
void _insertIntoChildList(ChildType child, { ChildType? after }) {
final ParentDataType childParentData = child.parentData! as ParentDataType;
//表示新增一个子节点
_childCount += 1;
//after == null表示这是多节点的第一个子节点
if (after == null) {
// insert at the start (_firstChild)
childParentData.nextSibling = _firstChild;
if (_firstChild != null) {
final ParentDataType _firstChildParentData = _firstChild!.parentData! as ParentDataType;
_firstChildParentData.previousSibling = child;
}
//传入的child作为第一个子节点
_firstChild = child;
//如果_lastChild为空 则将child设置为_lastChild
_lastChild ??= child;
} else {
final ParentDataType afterParentData = after.parentData! as ParentDataType;
//这里通过双向链表的结构关联器多个子节点
//前子节点的尾部指向为空
if (afterParentData.nextSibling == null) {
// insert at the end (_lastChild); we'll end up with two or more children
//传入的子节点的头部指向前一个子节点
childParentData.previousSibling = after;
//前子节点的尾部指向当前传入的child
afterParentData.nextSibling = child;
_lastChild = child;
} else {
//在一个完整的双向链表直接插入一个新的子节点
//新的子节点自然头部指向到前一个子节点,尾部指向就是前一个子节点的指向
childParentData.nextSibling = afterParentData.nextSibling;
childParentData.previousSibling = after;
final ParentDataType childPreviousSiblingParentData = childParentData.previousSibling!.parentData! as ParentDataType;
final ParentDataType childNextSiblingParentData = childParentData.nextSibling!.parentData! as ParentDataType;
//新的子节点的前一个子节点的next要指向新的子节点
//afterParentData.nextSibling = child
childPreviousSiblingParentData.nextSibling = child;
//新的子节点的后面的一个子节点的previous也要指向新的子节点
//nextParentData.previousSibling = child
childNextSiblingParentData.previousSibling = child;
}
}
}