RenderObjectWidget是Widget例如SizeBox,Column等
RenderObjectElement是這類Widget生成的Element類型,
例如SizeBox對應(yīng)SingleChildRenderObjectElement(單子節(jié)點(diǎn)的Element)
RenderObject才是真正負(fù)責(zé)繪制的對象,其中包含了paint,layout等方法~
Text組件為例:
class Text extends StatelessWidget
Textbuild返回的是
class RichText extends MultiChildRenderObjectWidget
MultiChildRenderObjectWidget - > MultiChildRenderObjectElement
abstract class MultiChildRenderObjectWidget extends RenderObjectWidget {
MultiChildRenderObjectElement createElement() => MultiChildRenderObjectElement(this);
創(chuàng)建關(guān)系:
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插入當(dāng)前的renderObject
_ancestorRenderObjectElement?.insertRenderObjectChild(renderObject, newSlot);
...
遍歷_parent(就是上個節(jié)點(diǎn)的element,這個_parent在每次的mount方法設(shè)置),一直遍歷知道找到最近的一個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 創(chuàng)建對應(yīng)的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);
}
總結(jié):
inflateWidget會觸發(fā)RenderObjectWidget的createElement創(chuàng)建RenderObjectElement,
再調(diào)用RenderObjectElement的mount方法
mount方法調(diào)用RenderObjectWidget的createRenderObject方法創(chuàng)建RenderObject
然后找到最近的一個父RenderObjectElement調(diào)用insertRenderObjectChild插入RenderObject
(注意:這里不是RenderObjectElement的child,而是RenderObjectElement關(guān)聯(lián)的RenderObject的child, element樹里面都是element, RenderObject樹里面都是RenderObject)
MultiChildRenderObjectElement多子節(jié)點(diǎn)掛載邏輯
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);
}
多節(jié)點(diǎn)添加子節(jié)點(diǎn)邏輯
每個子節(jié)點(diǎn)的parentData的after用來指向前一個子節(jié)點(diǎn) previous指向下一個子節(jié)點(diǎn)
-
Father有子節(jié)點(diǎn)s1 s2 s3
s2的parentData的previous會用來指向s1,s1的next會指向s2
以此類推
void _insertIntoChildList(ChildType child, { ChildType? after }) {
final ParentDataType childParentData = child.parentData! as ParentDataType;
//表示新增一個子節(jié)點(diǎn)
_childCount += 1;
//after == null表示這是多節(jié)點(diǎn)的第一個子節(jié)點(diǎn)
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作為第一個子節(jié)點(diǎn)
_firstChild = child;
//如果_lastChild為空 則將child設(shè)置為_lastChild
_lastChild ??= child;
} else {
final ParentDataType afterParentData = after.parentData! as ParentDataType;
//這里通過雙向鏈表的結(jié)構(gòu)關(guān)聯(lián)器多個子節(jié)點(diǎn)
//前子節(jié)點(diǎn)的尾部指向?yàn)榭? if (afterParentData.nextSibling == null) {
// insert at the end (_lastChild); we'll end up with two or more children
//傳入的子節(jié)點(diǎn)的頭部指向前一個子節(jié)點(diǎn)
childParentData.previousSibling = after;
//前子節(jié)點(diǎn)的尾部指向當(dāng)前傳入的child
afterParentData.nextSibling = child;
_lastChild = child;
} else {
//在一個完整的雙向鏈表直接插入一個新的子節(jié)點(diǎn)
//新的子節(jié)點(diǎn)自然頭部指向到前一個子節(jié)點(diǎn),尾部指向就是前一個子節(jié)點(diǎn)的指向
childParentData.nextSibling = afterParentData.nextSibling;
childParentData.previousSibling = after;
final ParentDataType childPreviousSiblingParentData = childParentData.previousSibling!.parentData! as ParentDataType;
final ParentDataType childNextSiblingParentData = childParentData.nextSibling!.parentData! as ParentDataType;
//新的子節(jié)點(diǎn)的前一個子節(jié)點(diǎn)的next要指向新的子節(jié)點(diǎn)
//afterParentData.nextSibling = child
childPreviousSiblingParentData.nextSibling = child;
//新的子節(jié)點(diǎn)的后面的一個子節(jié)點(diǎn)的previous也要指向新的子節(jié)點(diǎn)
//nextParentData.previousSibling = child
childNextSiblingParentData.previousSibling = child;
}
}
}