RenderRepaintBoundary class
A render object that owns a CellBuffer cache for its subtree's paint.
On the first frame (and any frame after something inside it changed), the boundary repaints its subtree into the cache and clears needsPaint. On subsequent frames it skips the subtree walk entirely and composites the cache into the destination (CellBuffer.compositeRectFrom) — one pass over the cached cells instead of a recursive paint chain.
This is a CPU paint-memoization, NOT Flutter's GPU compositing layer — there is no layer tree here, and it does not isolate the subtree from repaint the way a GPU layer does. Two limits to keep in mind: it caches paint, not layout (a render object that isn't marked for layout and gets the same constraints returns its cached size from RenderObject.layout, with or without a boundary), and every rendered frame is still compared cell by cell with the previous one (CellBuffer.diffAgainst), so the blit just repopulates cells that comparison re-examines.
The win is the skipped paint walk: on a localized update, a boundary'd
subtree blits its cache instead of re-running its paint chain. Measured on
the paint-walk probe this is ~3x even for trivially cheap rows and 6-16x for
styled ones — the walk over N siblings costs more than blitting N-1 caches
regardless of per-row cost, so the historical "neutral for cheap subtrees"
guidance held only for a SINGLE boundary in isolation, not for the
one-of-many-changes shape ListView auto-wraps. The cost is one reused
cache buffer per boundary (bounded by what's on screen). Reach for a direct
boundary when a subtree's neighbour churns and it doesn't; the list case is
handled for you.
The boundary is opaque to its caller: parents call paint(buffer, offset)
as usual; the cache discipline is internal. Use the RepaintBoundary
widget to wrap subtrees that are expensive to paint and change rarely.
- Inheritance
-
- Object
- RenderObject
- RenderRepaintBoundary
- Implemented types
Constructors
- RenderRepaintBoundary({bool cachingEnabled = true})
Properties
- cachingEnabled ↔ bool
-
Whether this boundary currently caches its subtree's paint.
getter/setter pair
- child ↔ RenderObject?
-
The single child render object, if any.
getter/setter pairoverride
- constraints → CellConstraints
-
The constraints from the most recent layout pass.
no setterinherited
- hashCode → int
-
The hash code for this object.
no setterinherited
- hasLayout → bool
-
Whether this render object has been laid out at least once.
no setterinherited
- hitTestsBeyondBounds → bool
-
Whether a point outside this render object's box can hit something in
its subtree. False by default: hit-testing prunes a subtree by its box,
as Flutter does, so a pointer event walks one chain of the tree rather
than every region. A container that places children outside its box
and wants them to stay interactive there — a
Stackwith an overflowingPositioned— answers true.no setterinherited - isRepaintBoundary → bool
-
Whether this render object owns its own paint cache (a
CellBufferit can blit instead of re-walking its subtree's paint). Override to true in subclasses that implement the cache discipline.no setteroverride - needsLayout → bool
-
Whether this render object must run performLayout the next time it is
reached with the same constraints. Constraints changes always force a new
layout even when this flag is false.
no setterinherited
- needsPaint ↔ bool
-
Whether the enclosing boundary's cache has been invalidated. Set true
by markNeedsLayout and markNeedsPaintOnly; subclasses that implement
a paint cache clear it once they have re-painted into their cache.
getter/setter pairinherited
- paintOverflow → CellRect?
-
Conservative local bounds when this subtree can paint outside size.
Null means its layout box contains all paint. Containers derive this
from presented children, their offsets and clips. Results are cached;
layout or paint invalidation invalidates the enclosing bounds as well.
Custom painters that draw beyond their box override computePaintOverflow.
no setterinherited
- parent → RenderObject?
-
no setterinherited
- parentData ↔ ParentData?
-
getter/setter pairinherited
- rootFrameDamage → RenderDamageTracker?
-
The frame damage tracker attached at this tree's root — the per-owner
object a render object publishes frame-scoped facts into — or null while
detached or before the first frame.
no setterinherited
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- size → CellSize
-
The size computed by the most recent layout pass.
no setterinherited
Methods
-
adoptChild(
RenderObject child) → void -
Attaches
childto this render object as its parent. Subclasses that hold children call this whenever they accept one; it also gives the parent a chance to ensure RenderObject.parentData is the right type via setupParentData.inherited -
attachFrameDamageTracker(
RenderDamageTracker tracker) → bool -
Attaches the per-runtime damage tracker at this (root) render object.
inherited
-
childClipOf(
RenderObject child) → CellRect? -
The clip this render object imposes on
child, in its own coordinates, or null when it does not clip. Usually the same rectangle for every child (a viewport); a container with several scrolling regions — a table with a pinned header — answers per child.override -
childOffsetOf(
RenderObject child) → CellOffset -
Where this render object paints
child, relative to its own origin.inherited -
computeMaxIntrinsicHeight(
int? width) → int -
The tallest this render object would want to be at the given
width.inherited -
computeMaxIntrinsicWidth(
int? height) → int -
The widest this render object would want to be at the given
height. Most relevant override: text returns its unwrapped width.inherited -
computeMinIntrinsicHeight(
int? width) → int -
The shortest this render object can be at the given
width.inherited -
computeMinIntrinsicWidth(
int? height) → int -
The narrowest width below which content would clip. Text-like leaves
can return a longest-token width if they word-wrap.
inherited
-
computePaintOverflow(
) → CellRect? -
inherited
-
dropChild(
RenderObject child) → void -
Detaches
childfrom this render object.inherited -
layout(
CellConstraints constraints) → CellSize -
Lays out this render object against
constraintsand returns the chosen size. Subclasses implement performLayout rather than overriding this; the framework needs the bookkeeping around it.inherited -
markAncestorRepaintBoundariesDirty(
) → void -
Marks every repaint boundary STRICTLY ABOVE this node as needing paint.
inherited
-
markNeedsLayout(
) → void -
Marks this render object and its ancestors as needing layout, and marks
the nearest enclosing repaint boundary as dirty. Use this for changes
that can affect size, child constraints, child offsets, or layout-derived
paint state.
inherited
-
markNeedsPaintOnly(
) → void -
Marks this render object's painted output as stale without touching
layout.
inherited
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
paint(
CellBuffer buffer, CellOffset offset) → void -
Paints this render object into
bufferatoffset: its origin in the buffer's coordinates. The buffer's bounds are the clip.inherited -
performLayout(
CellConstraints constraints) → CellSize -
Override to compute the chosen size and lay out children. Must
return a size that satisfies
constraints.override -
performPaint(
CellBuffer buffer, CellOffset offset) → void -
Paints this render object's cells into
bufferatoffset.override -
presentsChild(
RenderObject child) → bool -
Whether
childis presented this frame: painted and interactive. False for a child hidden by policy — an inactiveIndexedStackchild, a route under an opaque route, an overlay entry under an opaque one, a list row outside the mounted window, a contained-error subtree.inherited -
screenGeometry(
) → RenderGeometry? -
This render object's screen geometry, derived from layout state: where
it is, and how much of it is visible.
inherited
-
setupParentData(
RenderObject child) → void -
Override to install a subclass of ParentData on the child. The
default is a no-op; multi-child render objects override this so a
child's
parentDatais always the type that parent expects.inherited -
toString(
) → String -
A string representation of this object.
inherited
-
visitRenderChildren(
void visitor(RenderObject child)) → void -
Visits this render object's children in paint order. The default reads
the single-child / multi-child interfaces; a container whose
RenderObjectWithChildren.children accessor copies its list overrides
this to iterate in place, since hit-testing and geometry tooling walk
the tree on every event.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited