Flutter Overview
BuildOwner plays an important role in Element state management:
- Trace and manage elements (” dirty elements “) that need rebuild during UI update.
- When there is “Dirty Elements”, notify the engine in time so that the rebuild of “Dirty Elements” can be arranged on the next frame to refresh the UI.
- Manage elements in an inactive state.
This is the first Owner we encountered, followed by PipeOwner.
The entire “Element Tree” shares the same BuildOwner instance (global) and is passed from parent to Child Element during Element mount.
@mustCallSuper
void mount(Element? parent, dynamic newSlot) {
assert(_lifecycleState == _ElementLifecycle.initial);
assert(widget ! =null);
assert(_parent == null);
assert(parent == null || parent._lifecycleState == _ElementLifecycle.active);
assert(slot == null); _parent = parent; _slot = newSlot; _lifecycleState = _ElementLifecycle.active; _depth = _parent ! =null? _parent! .depth +1 : 1;
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();
}
Copy the code
This is the mount method on Element’s base class, and line 8 assigns parent. Owner to child.
BuildOwner instance by WidgetsBinding responsible for creating and assigned to the root node of the Element “Tree” RenderObjectToWidgetElement, then as the “Tree” Element to create step by step to child nodes. BuildOwner is not required to be manually instantiated unless off-screen immersion is required (in which case an off-screen Element tree is required).
BuildOwner two key member variables:
final _InactiveElements _inactiveElements = _InactiveElements();
final List<Element> _dirtyElements = <Element>[];
Copy the code
Their names make their purpose clear: they are used to store collected Inactive Elements and Dirty Elements, respectively.
Dirty Elements
So how does BuildOwner collect “Dirty Elements”? For an element that needs to be updated, the element. markNeedsBuild method is called first, as described earlier in the state. setState method:
void setState(VoidCallback fn) {
final dynamic result = fn() as dynamic;
_element.markNeedsBuild();
}
Copy the code
As follows, Element. The BuildOwner markNeedsBuild call. ScheduleBuildFor method:
void markNeedsBuild() { if (! _active) return; if (dirty) return; _dirty = true; owner.scheduleBuildFor(this); }Copy the code
BuildOwner. ScheduleBuildFor method did two things:
-
OnBuildScheduled is called. This method (which is actually a callback) tells Engine that the next frame needs to be updated.
-
Add Dirty Elements to the
_dirtyElements Copy the code
In the.
void scheduleBuildFor(Element element) { assert(element.owner == this); onBuildScheduled(); _dirtyElements.add(element); element._inDirtyList = true; } Copy the code
After that, when a new frame is drawn, WidgetsBinding. DrawFrame calls the BuildOwner. BuildScope method:
void buildScope(Element context, [ VoidCallback callback ]) {
if (callback == null && _dirtyElements.isEmpty)
return;
try {
if (callback != null) {
callback();
}
_dirtyElements.sort(Element._sort);
int dirtyCount = _dirtyElements.length;
int index = 0;
while (index < dirtyCount) {
_dirtyElements[index].rebuild();
index += 1;
}
} finally {
for (Element element in _dirtyElements) {
element._inDirtyList = false;
}
_dirtyElements.clear();
}
}
Copy the code
-
If there is a callback, perform the callback first (line 7);
-
Sort “dirty elements” by their depth on the “Element Tree” (parent before child) (line 10);
Why are they arranged like this? Ensure that parent is rebuilt before child, so that the child is not rebuilt repeatedly (because parent updates child recursively when rebuilding).
-
Call rebuild (line 14) to the elements in _dirtyElements in turn;
-
Clean up _dirtyElements (line 21).
Inactive Elements
An Inactive Element is an intermediate state between dispose or re-insert of an Element from an Element Tree. The main purpose of designing inactive state is to allow an Element with a Global key to move around the tree with inactive state.
BuildOwner is responsible for managing Inactive Elements, including adding, removing, and unmounting expired Inactive elements. More information on “Inactive Element” will be presented along with the introduction of Element.
summary
BuildOwner is primarily used to collect “Dirty Elements” that need to be rebuilt and Elements that are in an Inactive state.
Is over! It’s that simple. See you next time!