提前致敬:
一文读懂Flutter的三棵树渲染机制和原理
Element? updateChild(Element? child, Widget? newWidget, Object? newSlot) {
//如果没有下一个widget并且当前element有subElement需要将subElement释放
if (newWidget == null) {
if (child != null)
deactivateChild(child);
return null;
}
final Element newChild;
//如果有下一个widget并且有subElement,说明之前位置有对应的widget,我需要去判断怎么处理这个节点的subElement
if (child != null) {
bool hasSameSuperclass = true;
// When the type of a widget is changed between Stateful and Stateless via
// hot reload, the element tree will end up in a partially invalid state.
// That is, if the widget was a StatefulWidget and is now a StatelessWidget,
// then the element tree currently contains a StatefulElement that is incorrectly
// referencing a StatelessWidget (and likewise with StatelessElement).
//
// To avoid crashing due to type errors, we need to gently guide the invalid
// element out of the tree. To do so, we ensure that the `hasSameSuperclass` condition
// returns false which prevents us from trying to update the existing element
// incorrectly.
//
// For the case where the widget becomes Stateful, we also need to avoid
// accessing `StatelessElement.widget` as the cast on the getter will
// cause a type error to be thrown. Here we avoid that by short-circuiting
// the `Widget.canUpdate` check once `hasSameSuperclass` is false.
assert(() {
final int oldElementClass = Element._debugConcreteSubtype(child);
final int newWidgetClass = Widget._debugConcreteSubtype(newWidget);
//判断两次的element类型是否一样
hasSameSuperclass = oldElementClass == newWidgetClass;
return true;
}());
if (hasSameSuperclass && child.widget == newWidget) {
//如果element类型一样,并且两个widget是同一个widget,我就不需要更换element
if (child.slot != newSlot)
updateSlotForChild(child, newSlot);
newChild = child;
} else if (hasSameSuperclass && Widget.canUpdate(child.widget, newWidget)) {
//如果element类型一样,并且两个widget类型和key都一样,我就不需要更换element,只需要更换_widget为newWidget
if (child.slot != newSlot)
updateSlotForChild(child, newSlot);
child.update(newWidget);
assert(child.widget == newWidget);
assert(() {
child.owner!._debugElementWasRebuilt(child);
return true;
}());
newChild = child;
} else {
//其他的(主要包含widget类型不一样,key不一样,或者一个是StatefulWidget,一个是StatelessWidget)
//我需要销毁当前的childElement,然后创建新的childElement
deactivateChild(child);
assert(child._parent == null);
newChild = inflateWidget(newWidget, newSlot);
}
} else {
//如果之前没有child,说明,这个节点之前没有对应的widget,这个时候我不需要判断直接创建child就可以了
newChild = inflateWidget(newWidget, newSlot);
}
assert(() {
if (child != null)
_debugRemoveGlobalKeyReservation(child);
final Key? key = newWidget.key;
if (key is GlobalKey) {
assert(owner != null);
owner!._debugReserveGlobalKeyFor(this, newChild, key);
}
return true;
}());
//返回新的childElement(也可能是之前的)
return newChild;
}
网友评论