Class Element
- Direct Known Subclasses:
ComponentElement,ContainerElement,GridViewElement,RenderObjectElement
An Element is a persistent object: when a Widget rebuilds, its Element is reused if the type still matches. That reuse is the key to the framework's efficient updates.
Element's responsibilities:
- Holds a reference to the Widget (updated across rebuilds)
- Manages the child Element tree
- Coordinates Widget creation, update, and disposal
- Supplies a RenderNode for RenderObjectElement
Element types:
ComponentElement- composite, manages a child Widget (StatelessWidget/StatefulWidget)RenderObjectElement- render, corresponds to an actual RenderNode
- Since:
- 6.2.0
- Version:
- 1.0.0
- Author:
- UltiTools Team
- See Also:
-
Field Summary
Fields -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprotected voidAdds a child Element.voidassignContext(@NotNull BuildContext context) Assigns a Context to this Element (only used for the root Element or in tests).booleanChecks whether this Element can update to the given Widget.voidClears the dirty flag.Gets the list of child Elements.@NotNull BuildContextGets the build context.@Nullable ElementGets the parent Element.@NotNull WidgetGets the Widget associated with this Element.booleanisDirty()Checks whether this Element needs a rebuild.booleanChecks whether this Element is mounted.voidmarkChildNeedsBuild(@NotNull Element child) Marks a child Element as needing a rebuild.voidMarks this Element as needing a rebuild.voidMounts this Element into the tree.abstract voidPerforms a rebuild.voidsetRootBuildScheduler(@Nullable Runnable scheduler) Registers, on the mounted root Element, the callback that a "needs rebuild" bubble hands off to onGuiRenderer.toString()voidunmount()Removes this Element from the tree.voidUpdates this Element with a new Widget.protected @Nullable ElementupdateChild(@Nullable Widget newWidget, @Nullable Element oldChild) Updates a single child Element.updateChildren(@NotNull List<Element> oldChildren, @NotNull List<Widget> newWidgets) Reconciles a list of old child Elements against a list of new Widgets, pairing bySlotKeywhere a Widget declares one and falling back to positional (index) pairing where it does not -- so a caller that never supplies a key sees exactly the same index-based behaviour this method replaces.
-
Field Details
-
_widget
-
_parent
-
_children
-
_dirty
private boolean _dirty -
_mounted
private boolean _mounted -
_context
-
_rootBuildScheduler
-
-
Constructor Details
-
Element
-
-
Method Details
-
assignContext
Assigns a Context to this Element (only used for the root Element or in tests).- Parameters:
context- the BuildContext
-
mount
Mounts this Element into the tree.Called the first time the Element is inserted into the tree. Subclasses should perform initialization work here and mount their child Elements.
CR-01 (T-05-62 / #371): every
mount(Element)override in this codebase callssuper.mount(parent)before doing its own work (mounting children, running the firstperformRebuild(), etc.) -- this base method is therefore the single choke point through which the ENTIRE mounting recursion passes, one call per Element, regardless of subtype:ContainerElement/GridViewElement.mountChildren()callingchildElement.mount(this)for each child, and themount()->performRebuild()->updateChild()->mount()cascadeStatelessElement/StatefulElementdrive when composing a child Widget for the first time. Checking the depth HERE, rather than separately in every subclass's own mounting method, guards the mount recursion exactly once per node without needing to duplicate the check at each override.update()/unmount()'s own recursions need no separate guard: they only ever walk a subtree whose depth was already validated here when it was first mounted, so they can never exceedRenderDepthGuard.MAX_DEPTHwithout first passing through an unguardedmount()call -- which this check closes.- Parameters:
parent- the parent Element, or null if this is the root Element
-
update
Updates this Element with a new Widget.Called when the Widget rebuilds. Subclasses should update their reference to the Widget and perform any necessary updates.
- Parameters:
newWidget- the new Widget instance
-
canUpdate
Checks whether this Element can update to the given Widget.- Parameters:
newWidget- the new Widget- Returns:
- true if it can be updated
-
unmount
public void unmount()Removes this Element from the tree.Called when the Element is no longer needed. Subclasses should perform cleanup work here and unmount their child Elements.
-
markNeedsBuild
public void markNeedsBuild()Marks this Element as needing a rebuild.This schedules the framework to rebuild this Element on the next frame.
-
markChildNeedsBuild
Marks a child Element as needing a rebuild.- Parameters:
child- the child Element
-
setRootBuildScheduler
Registers, on the mounted root Element, the callback that a "needs rebuild" bubble hands off to onGuiRenderer.Framework-internal method -- only GuiRenderer calls this, when it mounts or remounts the root Element; module authors do not need to (and should not) call it themselves. On a non-root Element this field is always null, because bubbling forwards to the first ancestor with
_parent != nulland never reaches this branch.- Parameters:
scheduler- the callback invoked when the root needs a rebuild, typicallyGuiRenderer::scheduleBuild; passnullto unregister (when the renderer is destroyed)
-
performRebuild
public abstract void performRebuild()Performs a rebuild.Subclasses should implement this method to build or rebuild the Widget tree.
-
getWidget
Gets the Widget associated with this Element.- Returns:
- the Widget instance
- Throws:
IllegalStateException- if the Widget is null
-
getParent
Gets the parent Element.- Returns:
- the parent Element, or null at the root
-
getChildren
Gets the list of child Elements.- Returns:
- the child Element list, or an empty list if there are none
-
getContext
Gets the build context.- Returns:
- the BuildContext
-
isMounted
public boolean isMounted()Checks whether this Element is mounted.- Returns:
- true if mounted
-
isDirty
public boolean isDirty()Checks whether this Element needs a rebuild.- Returns:
- true if it needs a rebuild
-
clearDirty
public void clearDirty()Clears the dirty flag. -
addChild
Adds a child Element.- Parameters:
child- the child Element
-
updateChild
@Nullable protected @Nullable Element updateChild(@Nullable @Nullable Widget newWidget, @Nullable @Nullable Element oldChild) Updates a single child Element.This is the core method of reconciliation. It decides whether to reuse the existing Element or create a new one.
- Parameters:
newWidget- the new WidgetoldChild- the previous child Element, may be null- Returns:
- the updated Element
-
updateChildren
@NotNull protected @NotNull List<Element> updateChildren(@NotNull @NotNull List<Element> oldChildren, @NotNull @NotNull List<Widget> newWidgets) Reconciles a list of old child Elements against a list of new Widgets, pairing bySlotKeywhere a Widget declares one and falling back to positional (index) pairing where it does not -- so a caller that never supplies a key sees exactly the same index-based behaviour this method replaces.This is the shared implementation D-09 item 5 asks for:
ContainerElementandGridViewElementwere literal twins, each hand-rolling the sameMath.min(size)index pairing and never readingWidget.getKey(). Both now call this method instead of maintaining their own copy, so the two classes cannot drift apart the way they did before this plan.Algorithm: the old child Elements are first split into a keyed group and an unkeyed group. Iterating the new Widget list, a keyed Widget looks up its match in the keyed group, and an unkeyed Widget takes the next available Element from the unkeyed group, in order. A match is reused via
updateChild(Widget, Element)(or replaced there if its type no longer matches); no match means a new Element is created. After the pass, whatever remains in either group -- unclaimed by any new Widget -- is unmounted.- Parameters:
oldChildren- the previously-mounted child Elements, in their current ordernewWidgets- the new child Widgets, in their desired order- Returns:
- the reconciled child Elements, in
newWidgets' order
-
toString
-