RenderObjectWidget是Widget例如SizeBox,Column等
RenderObjectElement是这类Widget生成的Element类型,
例如SizeBox对应SingleChildRenderObjectElement(单子节点的Element)
RenderObject才是真正负责绘制的对象,其中包含了paint,layout等方法~
Text组件为例:
class Text extends StatelessWidget
Textbuild返回的是
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;
}
}
}