第一步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<Element> _dirtyElements = <Element>[];
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代码。