Flutter setState流程解析!BuildOwner是如何收集「Dirty Elements」的呢?

第一步setState

  @protected
  void setState(VoidCallback fn) {
    final Object? result = fn() as dynamic;
    _element!.markNeedsBuild();
  }

1.先执行fn();
2.然后调markNeedsBuild方法

void markNeedsBuild() {
  //对生命周期处于active状态的,直接return;
  if (_lifecycleState != _ElementLifecycle.active)
      return;
  //对已经标记dirty=true对不予重新标记。换句话言之,标记dirty的已经执行过此方法了。
  if (dirty)
      return;
  _dirty = true;//标记
  owner!.scheduleBuildFor(this);
}

owner 是BuildOwner的实例(整个element tree共享一个实例,全局的),owner重要的两个变量:

final _InactiveElements _inactiveElements = _InactiveElements();
final List _dirtyElements = [];

scheduleBuildFor方法实际是将当前已经标记dirty的element添加到_dirtyElements中

void scheduleBuildFor(Element element) {
 if (element._inDirtyList) {
   _scheduledFlushDirtyElements = true;
   return;
 }
 if (!_scheduledFlushDirtyElements && onBuildScheduled != null) {
     _scheduledFlushDirtyElements = true;
     //一个回调方法,通知engine下一帧需要坐哪些更新操作
     onBuildScheduled!();
 }
 _dirtyElements.add(element);
 element._inDirtyList = true;
}

此后,WidgetsBinding.drawFrame回调用BuildOwner.buildScope方法:

void buildScope(Element context, [ VoidCallback? callback ]) {
  if (callback == null && _dirtyElements.isEmpty)
      return;
  try {
    //如有回调,先执行回调 
    if (callback != null) {
      callback();
    }
    //对「dirty elements」按在「Element Tree」上的深度排序 (即 parent 排在 child 前面) 
    _dirtyElements.sort(Element._sort);
    int dirtyCount = _dirtyElements.length;
    int index = 0;
    //对_dirtyElements中的元素依次调用rebuild
    while (index < dirtyCount) {
      _dirtyElements[index].rebuild();
      index += 1;
    }
  } finally {
    //finally
    //遍历_dirtyElements将元素element的属性_inDirtyList设置成false
    //(_inDirtyList在Dirty的集合中 true 代表在,false不在)
    for (Element element in _dirtyElements) {
      element._inDirtyList = false;
    }
    //清空 _dirtyElements
    _dirtyElements.clear();
  }
}

end

注:assert断言只在调试模式下生效。故这里省略了assert代码。

你可能感兴趣的:(Flutter setState流程解析!BuildOwner是如何收集「Dirty Elements」的呢?)