第一步setState
@protected
void setState(VoidCallback fn) {
final Object? result = fn() as dynamic;
_element!.markNeedsBuild();
}
1.先執(zhí)行fn();
2.然后調(diào)markNeedsBuild方法
void markNeedsBuild() {
//對(duì)生命周期處于active狀態(tài)的,直接return;
if (_lifecycleState != _ElementLifecycle.active)
return;
//對(duì)已經(jīng)標(biāo)記dirty=true對(duì)不予重新標(biāo)記。換句話言之,標(biāo)記dirty的已經(jīng)執(zhí)行過(guò)此方法了。
if (dirty)
return;
_dirty = true;//標(biāo)記
owner!.scheduleBuildFor(this);
}
owner 是BuildOwner的實(shí)例(整個(gè)element tree共享一個(gè)實(shí)例,全局的),owner重要的兩個(gè)變量:
final _InactiveElements _inactiveElements = _InactiveElements();
final List<Element> _dirtyElements = <Element>[];
scheduleBuildFor方法實(shí)際是將當(dāng)前已經(jīng)標(biāo)記dirty的element添加到_dirtyElements中
void scheduleBuildFor(Element element) {
if (element._inDirtyList) {
_scheduledFlushDirtyElements = true;
return;
}
if (!_scheduledFlushDirtyElements && onBuildScheduled != null) {
_scheduledFlushDirtyElements = true;
//一個(gè)回調(diào)方法,通知engine下一幀需要坐哪些更新操作
onBuildScheduled!();
}
_dirtyElements.add(element);
element._inDirtyList = true;
}
此后,WidgetsBinding.drawFrame回調(diào)用BuildOwner.buildScope方法:
void buildScope(Element context, [ VoidCallback? callback ]) {
if (callback == null && _dirtyElements.isEmpty)
return;
try {
//如有回調(diào),先執(zhí)行回調(diào)
if (callback != null) {
callback();
}
//對(duì)「dirty elements」按在「Element Tree」上的深度排序 (即 parent 排在 child 前面)
_dirtyElements.sort(Element._sort);
int dirtyCount = _dirtyElements.length;
int index = 0;
//對(duì)_dirtyElements中的元素依次調(diào)用rebuild
while (index < dirtyCount) {
_dirtyElements[index].rebuild();
index += 1;
}
} finally {
//finally
//遍歷_dirtyElements將元素element的屬性_inDirtyList設(shè)置成false
//(_inDirtyList在Dirty的集合中 true 代表在,false不在)
for (Element element in _dirtyElements) {
element._inDirtyList = false;
}
//清空 _dirtyElements
_dirtyElements.clear();
}
}
end
注:assert斷言只在調(diào)試模式下生效。故這里省略了assert代碼。