RenderObjectElement class abstract

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:

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. It is generally recommended against specializing the widget getter and instead casting at the various call sites to avoid adding overhead outside of this particular implementation.

class FooElement extends RenderObjectElement {
  FooElement(super.widget);

  // Specializing the renderObject getter is fine because
  // it is not performance sensitive.
  @override
  RenderFoo get renderObject => super.renderObject as RenderFoo;

  void _foo() {
    // For the widget getter, though, we prefer to cast locally
    // since that results in better overall performance where the
    // casting isn't needed:
    final Foo foo = widget as Foo;
    // ...
  }

  // ...
}

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) 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.

A child's slot is determined when the parent calls updateChild to inflate the child (see the next section). It can be updated by calling updateSlotForChild.

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 in the mount and update methods 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 insertRenderObjectChild. If the descendant's slot changes identity, it will call moveRenderObjectChild. If a descendant goes away, it will call removeRenderObjectChild.

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
Implementers

Constructors

RenderObjectElement(RenderObjectWidget widget)
Creates an element that uses the given widget as its configuration.

Properties

buildScope BuildScope
A BuildScope whose dirty Elements can only be rebuilt by BuildOwner.buildScope calls whose context argument is an Element within this BuildScope.
no setterinherited
debugDoingBuild bool
Whether the widget is currently updating the widget or render tree.
no setteroverride
debugIsActive bool
Returns true if the Element is active.
no setterinherited
debugIsDefunct bool
Returns true if the Element is defunct.
no setterinherited
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.
no setterinherited
dirty bool
Returns true if the element has been marked as needing rebuilding.
no setterinherited
hashCode int
The hash code for this object.
no setterinherited
mounted bool
Whether the Widget this context is associated with is currently mounted in the widget tree.
no setterinherited
owner BuildOwner?
The object that manages the lifecycle of this element.
no setterinherited
renderObject RenderObject
The underlying RenderObject for this element.
no setteroverride
renderObjectAttachingChild Element?
Returns the child of this Element that will insert a RenderObject into an ancestor of this Element to construct the render tree.
no setteroverride
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
size Size?
The size of the RenderBox returned by findRenderObject.
no setterinherited
slot Object?
Information set by parent to define where this child fits in its parent's child list.
no setterinherited
widget Widget
The configuration for this element.
no setterinherited

Methods

activate() → void
Transition from the "inactive" to the "active" lifecycle state.
inherited
attachNotificationTree() → void
Called in Element.mount and Element.activate to register this element in the notification tree.
inherited
attachRenderObject(Object? newSlot) → void
Add renderObject to the render tree at the location specified by newSlot.
override
deactivate() → void
Transition from the "active" to the "inactive" lifecycle state.
override
deactivateChild(Element child) → void
Move the given element to the list of inactive elements and detach its render object from the render tree.
inherited
debugDeactivated() → void
Called, in debug mode, after children have been deactivated (see deactivate).
inherited
debugDescribeChildren() List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children.
inherited
debugExpectsRenderObjectForSlot(Object? slot) bool
Whether the child in the provided slot (or one of its descendants) must insert a RenderObject into its ancestor RenderObjectElement by calling RenderObjectElement.insertRenderObjectChild on it.
inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node.
override
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
dependOnInheritedElement(InheritedElement ancestor, {Object? aspect}) InheritedWidget
Registers this build context with ancestor such that when ancestor's widget changes this build context is rebuilt.
inherited
dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({Object? aspect}) → T?
Returns the nearest widget of the given type T and creates a dependency on it, or null if no appropriate widget is found.
inherited
describeElement(String name, {DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty}) DiagnosticsNode
Returns a description of the Element associated with the current build context.
inherited
describeMissingAncestor({required Type expectedAncestorType}) List<DiagnosticsNode>
Adds a description of a specific type of widget missing from the current build context's ancestry tree.
inherited
describeOwnershipChain(String name) DiagnosticsNode
Adds a description of the ownership chain from a specific Element to the error report.
inherited
describeWidget(String name, {DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty}) DiagnosticsNode
Returns a description of the Widget associated with the current build context.
inherited
detachRenderObject() → void
Remove renderObject from the render tree.
override
didChangeDependencies() → void
Called when a dependency of this element changes.
inherited
dispatchNotification(Notification notification) → void
Start bubbling this notification at the given build context.
inherited
doesDependOnInheritedElement(InheritedElement ancestor) bool
Returns true if dependOnInheritedElement was previously called with ancestor.
inherited
findAncestorRenderObjectOfType<T extends RenderObject>() → T?
Returns the RenderObject object of the nearest ancestor RenderObjectWidget widget that is an instance of the given type T.
inherited
findAncestorStateOfType<T extends State<StatefulWidget>>() → T?
Returns the State object of the nearest ancestor StatefulWidget widget that is an instance of the given type T.
inherited
findAncestorWidgetOfExactType<T extends Widget>() → T?
Returns the nearest ancestor widget of the given type T, which must be the type of a concrete Widget subclass.
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
findRootAncestorStateOfType<T extends State<StatefulWidget>>() → T?
Returns the State object of the furthest ancestor StatefulWidget widget that is an instance of the given type T.
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.
inherited
getElementForInheritedWidgetOfExactType<T extends InheritedWidget>() InheritedElement?
Obtains the element corresponding to the nearest widget of the given type T, which must be the type of a concrete InheritedWidget subclass.
inherited
getInheritedWidgetOfExactType<T extends InheritedWidget>() → T?
Returns the nearest widget of the given InheritedWidget subclass T or null if an appropriate ancestor is not found.
inherited
inflateWidget(Widget newWidget, Object? newSlot) Element
Create an element for the given widget and add it as a child of this element in the given slot.
inherited
insertRenderObjectChild(covariant RenderObject child, covariant Object? slot) → void
Insert the given child into renderObject at the given slot.
markNeedsBuild() → void
Marks the element as dirty and adds it to the global list of widgets to rebuild in the next frame.
inherited
mount(Element? parent, Object? newSlot) → void
Add this element to the tree in the given slot of the given parent.
override
moveRenderObjectChild(covariant RenderObject child, covariant Object? oldSlot, covariant Object? newSlot) → void
Move the given child from the given old slot to the given new slot.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
performRebuild() → void
Cause the widget to update itself.
override
reassemble() → void
Called whenever the application is reassembled during debugging, for example during hot reload.
inherited
rebuild({bool force = false}) → void
Cause the widget to update itself. In debug builds, also verify various invariants.
inherited
removeRenderObjectChild(covariant RenderObject child, covariant Object? slot) → void
Remove the given child from renderObject.
toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep.
inherited
toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) String
A string representation of this object.
inherited
toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) 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
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
updateChild(Element? child, Widget? newWidget, Object? newSlot) Element?
Update the given child with the given new configuration.
inherited
updateChildren(List<Element> oldChildren, List<Widget> newWidgets, {Set<Element>? forgottenChildren, List<Object?>? slots}) List<Element>
Updates the children of this element to use new widgets.
inherited
updateSlot(Object? newSlot) → void
Called by updateSlotForChild when the framework needs to change the slot that this Element occupies in its ancestor.
override
updateSlotForChild(Element child, Object? newSlot) → void
Change the slot that the given child occupies in its parent.
inherited
visitAncestorElements(ConditionalElementVisitor visitor) → void
Walks the ancestor chain, starting with the parent of this build context's widget, invoking the argument for each ancestor.
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
Compare two widgets for equality.
inherited