RenderObjectElement class
An Element that uses a RenderObjectWidget as its configuration.
RenderObjectElement objects have an associated RenderObject widget in the render tree, which handles concrete operations like laying out, painting, and hit testing.
Contrast with ComponentElement.
For details on the lifecycle of an element, see the discussion at Element.
Writing a RenderObjectElement subclass
There are three common child models used by most RenderObjects:
-
Leaf render objects, with no children: The LeafRenderObjectElement class handles this case.
-
A single child: The SingleChildRenderObjectElement class handles this case.
-
A linked list of children: The MultiChildRenderObjectElement class handles this case.
Sometimes, however, a render object's child model is more complicated. Maybe it has a two-dimensional array of children. Maybe it constructs children on demand. Maybe it features multiple lists. In such situations, the corresponding Element for the Widget that configures that RenderObject will be a new subclass of RenderObjectElement.
Such a subclass is responsible for managing children, specifically the Element children of this object, and the RenderObject children of its corresponding RenderObject.
Specializing the getters
RenderObjectElement objects spend much of their time acting as intermediaries between their widget and their renderObject. To make this more tractable, most RenderObjectElement subclasses override these getters so that they return the specific type that the element expects, e.g.:
class FooElement extends RenderObjectElement {
@override
Foo get widget => super.widget;
@override
RenderFoo get renderObject => super.renderObject;
// ...
}
Slots
Each child Element corresponds to a RenderObject which should be attached to this element's render object as a child.
However, the immediate children of the element may not be the ones that eventually produce the actual RenderObject that they correspond to. For example a StatelessElement (the element of a StatelessWidget) simply corresponds to whatever RenderObject its child (the element returned by its StatelessWidget.build method) corresponds to.
Each child is therefore assigned a slot token. This is an identifier whose meaning is private to this RenderObjectElement node. When the descendant that finally produces the RenderObject is ready to attach it to this node's render object, it passes that slot token back to this node, and that allows this node to cheaply identify where to put the child render object relative to the others in the parent render object.
Updating children
Early in the lifecycle of an element, the framework calls the mount method. This method should call updateChild for each child, passing in the widget for that child, and the slot for that child, thus obtaining a list of child Elements.
Subsequently, the framework will call the update method. In this method, the RenderObjectElement should call updateChild for each child, passing in the Element that was obtained during mount or the last time update was run (whichever happened most recently), the new Widget, and the slot. This provides the object with a new list of Element objects.
Where possible, the update method should attempt to map the elements from the last pass to the widgets in the new pass. For example, if one of the elements from the last pass was configured with a particular Key, and one of the widgets in this new pass has that same key, they should be paired up, and the old element should be updated with the widget (and the slot corresponding to the new widget's new position, also). The updateChildren method may be useful in this regard.
updateChild should be called for children in their logical order. The
order can matter; for example, if two of the children use PageStorage's
writeState
feature in their build method (and neither has a Widget.key),
then the state written by the first will be overwritten by the second.
Dynamically determining the children during the build phase
The child widgets need not necessarily come from this element's widget verbatim. They could be generated dynamically from a callback, or generated in other more creative ways.
Dynamically determining the children during layout
If the widgets are to be generated at layout time, then generating them when the update method won't work: layout of this element's render object hasn't started yet at that point. Instead, the update method can mark the render object as needing layout (see RenderObject.markNeedsLayout), and then the render object's RenderObject.performLayout method can call back to the element to have it generate the widgets and call updateChild accordingly.
For a render object to call an element during layout, it must use RenderObject.invokeLayoutCallback. For an element to call updateChild outside of its update method, it must use BuildOwner.buildScope.
The framework provides many more checks in normal operation than it does when doing a build during layout. For this reason, creating widgets with layout-time build semantics should be done with great care.
Handling errors when building
If an element calls a builder function to obtain widgets for its children, it may find that the build throws an exception. Such exceptions should be caught and reported using FlutterError.reportError. If a child is needed but a builder has failed in this way, an instance of ErrorWidget can be used instead.
Detaching children
It is possible, when using GlobalKeys, for a child to be proactively removed by another element before this element has been updated. (Specifically, this happens when the subtree rooted at a widget with a particular GlobalKey is being moved from this element to an element processed earlier in the build phase.) When this happens, this element's forgetChild method will be called with a reference to the affected child element.
The forgetChild method of a RenderObjectElement subclass must remove the child element from its child list, so that when it next updates its children, the removed child is not considered.
For performance reasons, if there are many elements, it may be quicker to track which elements were forgotten by storing them in a Set, rather than proactively mutating the local record of the child list and the identities of all the slots. For example, see the implementation of MultiChildRenderObjectElement.
Maintaining the render object tree
Once a descendant produces a render object, it will call insertChildRenderObject. If the descendant's slot changes identity, it will call moveChildRenderObject. If a descendant goes away, it will call removeChildRenderObject.
These three methods should update the render tree accordingly, attaching, moving, and detaching the given child render object from this element's own render object respectively.
Walking the children
If a RenderObjectElement object has any children Elements, it must expose them in its implementation of the visitChildren method. This method is used by many of the framework's internal mechanisms, and so should be fast. It is also used by the test framework and debugDumpApp.
- Inheritance
- Object
- Diagnosticable
- DiagnosticableTree
- Element
- RenderObjectElement
- Implementers
Constructors
- RenderObjectElement(RenderObjectWidget widget)
- Creates an element that uses the given widget as its configuration.
Properties
- renderObject → RenderObject
-
The underlying RenderObject for this element.
read-only, override
- widget → RenderObjectWidget
-
The configuration for this element.
read-only, override
- depth → int
-
An integer that is guaranteed to be greater than the parent's, if any.
The element at the root of the tree must have a depth greater than 0.
read-only, inherited
- dirty → bool
-
Returns true if the element has been marked as needing rebuilding.
read-only, inherited
- hashCode → int
-
The hash code for this object. [...]
read-only, inherited
- owner → BuildOwner
-
The object that manages the lifecycle of this element.
read-only, inherited
- runtimeType → Type
-
A representation of the runtime type of the object.
read-only, inherited
- size → Size
-
The size of the RenderBox returned by findRenderObject. [...]
read-only, inherited
- slot → dynamic
-
Information set by parent to define where this child fits in its parent's
child list. [...]
read-only, inherited
Methods
-
attachRenderObject(
dynamic newSlot) → void -
Add renderObject to the render tree at the location specified by slot. [...]
override
-
deactivate(
) → void -
Transition from the "active" to the "inactive" lifecycle state. [...]
override
-
debugFillProperties(
DiagnosticPropertiesBuilder properties) → void -
Add additional properties associated with the node. [...]
override
-
detachRenderObject(
) → void -
Remove renderObject from the render tree. [...]
override
-
insertChildRenderObject(
covariant RenderObject child, covariant dynamic slot) → void -
Insert the given child into renderObject at the given slot. [...]
@protected
-
mount(
Element parent, dynamic newSlot) → void -
Add this element to the tree in the given slot of the given parent. [...]
override
-
moveChildRenderObject(
covariant RenderObject child, covariant dynamic slot) → void -
Move the given child to the given slot. [...]
@protected
-
performRebuild(
) → void -
Called by rebuild() after the appropriate checks have been made.
override
-
removeChildRenderObject(
covariant RenderObject child) → void -
Remove the given child from renderObject. [...]
@protected
-
unmount(
) → void -
Transition from the "inactive" to the "defunct" lifecycle state. [...]
override
-
update(
covariant RenderObjectWidget newWidget) → void -
Change the widget used to configure this element. [...]
override
-
updateChildren(
List< Element> oldChildren, List< Widget> newWidgets, { Set< Element> forgottenChildren }) → List< Element> -
Updates the children of this element to use new widgets. [...]
@protected
-
activate(
) → void -
Transition from the "inactive" to the "active" lifecycle state. [...]
@mustCallSuper, inherited
-
ancestorInheritedElementForWidgetOfExactType(
Type targetType) → InheritedElement -
Obtains the element corresponding to the nearest widget of the given type,
which must be the type of a concrete InheritedWidget subclass. [...]
inherited
-
ancestorRenderObjectOfType(
TypeMatcher matcher) → RenderObject -
Returns the RenderObject object of the nearest ancestor RenderObjectWidget widget
that matches the given TypeMatcher. [...]
inherited
-
ancestorStateOfType(
TypeMatcher matcher) → State< StatefulWidget> -
Returns the State object of the nearest ancestor StatefulWidget widget
that matches the given TypeMatcher. [...]
inherited
-
ancestorWidgetOfExactType(
Type targetType) → Widget -
Returns the nearest ancestor widget of the given type, which must be the
type of a concrete Widget subclass. [...]
inherited
-
deactivateChild(
Element child) → void -
Move the given element to the list of inactive elements and detach its
render object from the render tree. [...]
@protected, inherited
-
debugDeactivated(
) → void -
Called, in debug mode, after children have been deactivated (see deactivate). [...]
@mustCallSuper, inherited
-
debugDescribeChildren(
) → List< DiagnosticsNode> -
Returns a list of DiagnosticsNode objects describing this node's
children. [...]
inherited
-
debugGetCreatorChain(
int limit) → String -
Returns a description of what caused this element to be created. [...]
inherited
-
debugGetDiagnosticChain(
) → List< Element> -
Returns the parent chain from this element back to the root of the tree. [...]
inherited
-
debugVisitOnstageChildren(
ElementVisitor visitor) → void -
Calls the argument for each child considered onstage. [...]
inherited
-
didChangeDependencies(
) → void -
Called when a dependency of this element changes. [...]
@mustCallSuper, inherited
-
findRenderObject(
) → RenderObject -
The current RenderObject for the widget. If the widget is a
RenderObjectWidget, this is the render object that the widget created
for itself. Otherwise, it is the render object of the first descendant
RenderObjectWidget. [...]
inherited
-
forgetChild(
Element child) → void -
Remove the given child from the element's child list, in preparation for
the child being reused elsewhere in the element tree. [...]
@protected, inherited
-
inflateWidget(
Widget newWidget, dynamic newSlot) → Element -
Create an element for the given widget and add it as a child of this
element in the given slot. [...]
@protected, inherited
-
inheritFromElement(
InheritedElement ancestor, { Object aspect }) → InheritedWidget -
Registers this build context with
ancestor
such that whenancestor
's widget changes this build context is rebuilt. [...]inherited -
inheritFromWidgetOfExactType(
Type targetType, { Object aspect }) → InheritedWidget -
Obtains the nearest widget of the given type, which must be the type of a
concrete InheritedWidget subclass, and registers this build context with
that widget such that when that widget changes (or a new widget of that
type is introduced, or the widget goes away), this build context is
rebuilt so that it can obtain new values from that widget. [...]
inherited
-
markNeedsBuild(
) → void -
Marks the element as dirty and adds it to the global list of widgets to
rebuild in the next frame. [...]
inherited
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a non-existent method or property is accessed. [...]
inherited
-
rebuild(
) → void -
Called by the BuildOwner when BuildOwner.scheduleBuildFor has been
called to mark this element dirty, by mount when the element is first
built, and by update when the widget has changed.
inherited
-
rootAncestorStateOfType(
TypeMatcher matcher) → State< StatefulWidget> -
Returns the State object of the furthest ancestor StatefulWidget widget
that matches the given TypeMatcher. [...]
inherited
-
toDiagnosticsNode(
{String name, DiagnosticsTreeStyle style }) → DiagnosticsNode -
Returns a debug representation of the object that is used by debugging
tools and by toStringDeep. [...]
inherited
-
toString(
{DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String -
Returns a string representation of this object.
inherited
-
toStringDeep(
{String prefixLineOne: '', String prefixOtherLines, DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String -
Returns a string representation of this node and its descendants. [...]
inherited
-
toStringShallow(
{String joiner: ', ', DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String -
Returns a one-line detailed description of the object. [...]
inherited
-
toStringShort(
) → String -
A short, textual description of this element.
inherited
-
updateChild(
Element child, Widget newWidget, dynamic newSlot) → Element -
Update the given child with the given new configuration. [...]
@protected, inherited
-
updateSlotForChild(
Element child, dynamic newSlot) → void -
Change the slot that the given child occupies in its parent. [...]
@protected, inherited
-
visitAncestorElements(
bool visitor(Element element)) → void -
Walks the ancestor chain, starting with the parent of this build context's
widget, invoking the argument for each ancestor. The callback is given a
reference to the ancestor widget's corresponding Element object. The
walk stops when it reaches the root widget or when the callback returns
false. The callback must not return null. [...]
inherited
-
visitChildElements(
ElementVisitor visitor) → void -
Wrapper around visitChildren for BuildContext.
inherited
-
visitChildren(
ElementVisitor visitor) → void -
Calls the argument for each child. Must be overridden by subclasses that
support having children. [...]
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator. [...]
inherited