美文网首页
flutter渲染中的三棵树

flutter渲染中的三棵树

作者: 晨曦中的花豹 | 来源:发表于2021-10-29 16:46 被阅读0次

提前致敬:
一文读懂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;
}

相关文章

网友评论

      本文标题:flutter渲染中的三棵树

      本文链接:https://www.haomeiwen.com/subject/sdgialtx.html