Flutter setState 后 Element和RenderObject的更新

1,404 阅读3分钟

setState之后

以下代码会删除断言等不是核心的代理

State > setState

  @protected
  void setState(VoidCallback fn) {
    ///执行setState包裹的匿名函数
    final dynamic result = fn() as dynamic;
    ///将当前element标记为dirty,需要更新的
    _element.markNeedsBuild();
  }

Element > markNeedsBuild

标记当前element为dirty

void markNeedsBuild() {
  /// 如果不是活跃的组件不需要更新
  if (_lifecycleState != _ElementLifecycle.active) {
    return;
  }
  /// 如果组件已标记为dirty则不需要重复标记
  if (dirty) {
    return;
  }
  /// 将组件标记为dirty
  _dirty = true;
  owner!.scheduleBuildFor(this);
}

BuildOwner > scheduleBuildFor

void scheduleBuildFor(Element element) {
  ///判断当前更新的element当前已在_dirtyElements数组里
  if (element._inDirtyList) {
    _dirtyElementsNeedsResorting = true;
    return;
  }
  if (!_scheduledFlushDirtyElements && onBuildScheduled != null) {
    _scheduledFlushDirtyElements = true;
    onBuildScheduled();
  }
  ///将当前的element添加到_dirtyElements
  _dirtyElements.add(element);
  
  /// 向脏元素列表添加这个element
  element._inDirtyList = true;
}

Element 和 RenderObject更新

WidgetsBinding > drawFrame

Flutter 会在下一帧的时候调用drawFrame

void drawFrame() {
  if (renderViewElement != null)
    //这里执行的是dirtyElement的更新
    buildOwner.buildScope(renderViewElement);
  //这里更新的RenderObject的更新
  super.drawFrame();
}

BuildOwner > buildScope

这里的BuildOwner就是上面把element添加到dirtyElements里的owner

void buildScope(Element context, [ VoidCallback callback ]) {
  ...
  while (index < dirtyCount) {
    ///对每个dirtyElement执行rebuild
    _dirtyElements[index].rebuild();
    index += 1;
  }
  ...
}

Element > rebuild

void rebuild() {
  if (!_active || !_dirty)
    return;
  ///
  performRebuild();
}

ComponentElement > performRebuild

这里是ComponentElement的更新

void performRebuild() {
  Widget built;
  try {
    ///这里的built就是StatelessWidget的build和StatefulWidget State的build所返回的widget
    built = build();
  } catch (e, stack) {
  } finally {
   ///这里设置当前dirty为false,防止后面update的时候递归
    _dirty = false;
  }
  try {
    ///更新子element,这里的_child是子element, built是当前element的build返回的widget,也就是子widget,它们的关系会在下面其他理清
    _child = updateChild(_child, built, slot);
  } catch (e, stack) {
  }
}

Element > updateChild

Element updateChild(Element child, Widget newWidget, dynamic newSlot) {
  if (newWidget == null) {
    if (child != null)
      ///如果build返回的widget是null,但是当前element不为null的话销毁这个element
      deactivateChild(child);
    return null;
  }
  Element newChild;
  ///如果child不为null则判断是否需要更新或重新创建
  if (child != null) {
    bool hasSameSuperclass = true;
    if (hasSameSuperclass && child.widget == newWidget) {
      if (child.slot != newSlot)
        updateSlotForChild(child, newSlot);
      ///如果element的widget和新build返回的widget相同的话则返回当前element
      ///这里可以发现两个widget相等的情况下会少出发child.update(newWidget)
      ///这里可以用const Widget来优化
      newChild = child;
    } else if (hasSameSuperclass && Widget.canUpdate(child.widget, newWidget)) {
      if (child.slot != newSlot)
        updateSlotForChild(child, newSlot);
      ///如果element的widget和新build返回的widget的runTimeType和key相同的话
      ///则用新的widget更新到element
      child.update(newWidget);
      newChild = child;
    } else {
      ///销毁当前element
      deactivateChild(child);
      ///用newWidget的createElement创建一个新的element
      newChild = inflateWidget(newWidget, newSlot);
    }
  } else {
    newChild = inflateWidget(newWidget, newSlot);
  }
  return newChild;
}

其他

Element里的_owner

这里的_owner是所有element使用的都是同一个owner

初始化 | WidgetsBinding > initInstances

@override
void initInstances() {
  super.initInstances();
  _instance = this;
  _buildOwner = BuildOwner();
 ...
}

绑定到顶层element | RenderObjectToWidgetAdapter > attachToRenderTree

  RenderObjectToWidgetElement<T> attachToRenderTree(BuildOwner owner, [ RenderObjectToWidgetElement<T> element ]) {
  if (element == null) {
    owner.lockState(() {
      element = createElement();
      ///这里设置了顶层element的owner
      element.assignOwner(owner);
    });
    owner.buildScope(element, () {
      element.mount(null, null);
    });
    SchedulerBinding.instance.ensureVisualUpdate();
  } else {
    element._newWidget = this;
    element.markNeedsBuild();
  }
  return element;
}

子element引用父element的owner | Element > mount

@mustCallSuper
void mount(Element parent, dynamic newSlot) {
  _parent = parent;
  _slot = newSlot;
  _depth = _parent != null ? _parent.depth + 1 : 1;
  _active = true;
  ///为每个子element引用夫element的owner
  if (parent != null) // Only assign ownership if the parent is non-null
    _owner = parent.owner;
  final Key key = widget.key;
  if (key is GlobalKey) {
    key._register(this);
  }
  _updateInheritance();
}

Element的widget和 _child 和build 之间的关系

测试代码

class First extends StatefulWidget {
  @override
  _FirstState createState() => _FirstState();
}

class _FirstState extends State<First> {
  @override
  Widget build(BuildContext context) {
    return Second();
  }
}

class Second extends StatefulWidget {
  @override
  _SecondState createState() => _SecondState();
}

class _SecondState extends State<Second> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

/// FirstStatefulElement > widget = First
/// FirstStatefulElement > build() = Second
/// FirstComponentElement > _child = SecondElement
/// SecondStatefulElement > widget = Second

/// FirstComponentElement._child 和 FirstComponentElement Build() = SecondStatefulElement 和 Second
///_child = updateChild(_child, built, slot); 等价于 SecondElement = updateChild(SecondElement, Second, slot)

未完待续