@@ -92,6 +92,10 @@ abstract class AbstractLayoutBuilder<LayoutInfoType> extends RenderObjectWidget
92
92
///
93
93
/// The [builder] function is _not_ called during layout if the parent passes
94
94
/// the same constraints repeatedly.
95
+ ///
96
+ /// In the event that an ancestor skips the layout of this subtree so the
97
+ /// constraints become outdated, the `builder` rebuilds with the last known
98
+ /// constraints.
95
99
/// {@endtemplate}
96
100
abstract class ConstrainedLayoutBuilder <ConstraintType extends Constraints >
97
101
extends AbstractLayoutBuilder <ConstraintType > {
@@ -133,7 +137,7 @@ class _LayoutBuilderElement<LayoutInfoType> extends RenderObjectElement {
133
137
SchedulerPhase .persistentCallbacks => false ,
134
138
};
135
139
if (! deferMarkNeedsLayout) {
136
- renderObject.markNeedsLayout ();
140
+ renderObject.scheduleLayoutCallback ();
137
141
return ;
138
142
}
139
143
_deferredCallbackScheduled = true ;
@@ -145,7 +149,7 @@ class _LayoutBuilderElement<LayoutInfoType> extends RenderObjectElement {
145
149
// This method is only called when the render tree is stable, if the Element
146
150
// is deactivated it will never be reincorporated back to the tree.
147
151
if (mounted) {
148
- renderObject.markNeedsLayout ();
152
+ renderObject.scheduleLayoutCallback ();
149
153
}
150
154
}
151
155
@@ -180,7 +184,7 @@ class _LayoutBuilderElement<LayoutInfoType> extends RenderObjectElement {
180
184
renderObject._updateCallback (_rebuildWithConstraints);
181
185
if (newWidget.updateShouldRebuild (oldWidget)) {
182
186
_needsBuild = true ;
183
- renderObject.markNeedsLayout ();
187
+ renderObject.scheduleLayoutCallback ();
184
188
}
185
189
}
186
190
@@ -190,7 +194,7 @@ class _LayoutBuilderElement<LayoutInfoType> extends RenderObjectElement {
190
194
// to performRebuild since this call already does what performRebuild does,
191
195
// So the element is clean as soon as this method returns and does not have
192
196
// to be added to the dirty list or marked as dirty.
193
- renderObject.markNeedsLayout ();
197
+ renderObject.scheduleLayoutCallback ();
194
198
_needsBuild = true ;
195
199
}
196
200
@@ -202,14 +206,14 @@ class _LayoutBuilderElement<LayoutInfoType> extends RenderObjectElement {
202
206
// Force the callback to be called, even if the layout constraints are the
203
207
// same. This is because that callback may depend on the updated widget
204
208
// configuration, or an inherited widget.
205
- renderObject.markNeedsLayout ();
209
+ renderObject.scheduleLayoutCallback ();
206
210
_needsBuild = true ;
207
211
super .performRebuild (); // Calls widget.updateRenderObject (a no-op in this case).
208
212
}
209
213
210
214
@override
211
215
void unmount () {
212
- renderObject._updateCallback ( null ) ;
216
+ renderObject._callback = null ;
213
217
super .unmount ();
214
218
}
215
219
@@ -295,39 +299,36 @@ class _LayoutBuilderElement<LayoutInfoType> extends RenderObjectElement {
295
299
/// Generic mixin for [RenderObject] s created by an [AbstractLayoutBuilder] with
296
300
/// the the same `LayoutInfoType` .
297
301
///
298
- /// Provides a [rebuildIfNecessary] method that should be called at layout time,
299
- /// typically in [RenderObject.performLayout] . The method invokes
300
- /// [AbstractLayoutBuilder] 's builder callback if needed.
302
+ /// Provides a [layoutCallback] implementation which, if needed, invokes
303
+ /// [AbstractLayoutBuilder] 's builder callback.
301
304
///
302
305
/// Implementers must provide a [layoutInfo] implementation that is safe to
303
- /// access in [rebuildIfNecessary ] , which is typically called in [performLayout] .
306
+ /// access in [layoutCallback ] , which is called in [performLayout] .
304
307
mixin RenderAbstractLayoutBuilderMixin <LayoutInfoType , ChildType extends RenderObject >
305
- on RenderObjectWithChildMixin <ChildType > {
308
+ on RenderObjectWithChildMixin <ChildType >, RenderObjectWithLayoutCallbackMixin {
306
309
LayoutCallback <Constraints >? _callback;
307
310
308
311
/// Change the layout callback.
309
- void _updateCallback (LayoutCallback <Constraints >? value) {
312
+ void _updateCallback (LayoutCallback <Constraints > value) {
310
313
if (value == _callback) {
311
314
return ;
312
315
}
313
316
_callback = value;
314
- markNeedsLayout ();
317
+ scheduleLayoutCallback ();
315
318
}
316
319
317
- /// Invoke the builder callback supplied via [AbstractLayoutBuilder] and
320
+ /// Invokes the builder callback supplied via [AbstractLayoutBuilder] and
318
321
/// rebuilds the [AbstractLayoutBuilder] 's widget tree, if needed.
319
322
///
320
- /// No work will be done if [layoutInfo] has not changed since the last time
321
- /// this method was called, and [AbstractLayoutBuilder.updateShouldRebuild]
323
+ /// No further work will be done if [layoutInfo] has not changed since the last
324
+ /// time this method was called, and [AbstractLayoutBuilder.updateShouldRebuild]
322
325
/// returned `false` when the widget was rebuilt.
323
326
///
324
327
/// This method should typically be called as soon as possible in the class's
325
328
/// [performLayout] implementation, before any layout work is done.
326
- @protected
327
- void rebuildIfNecessary () {
328
- assert (_callback != null );
329
- invokeLayoutCallback (_callback! );
330
- }
329
+ @visibleForOverriding
330
+ @override
331
+ void layoutCallback () => _callback !(constraints);
331
332
332
333
/// The information to invoke the [AbstractLayoutBuilder.builder] callback with.
333
334
///
@@ -381,6 +382,7 @@ class LayoutBuilder extends ConstrainedLayoutBuilder<BoxConstraints> {
381
382
class _RenderLayoutBuilder extends RenderBox
382
383
with
383
384
RenderObjectWithChildMixin <RenderBox >,
385
+ RenderObjectWithLayoutCallbackMixin ,
384
386
RenderAbstractLayoutBuilderMixin <BoxConstraints , RenderBox > {
385
387
@override
386
388
double computeMinIntrinsicWidth (double height) {
@@ -433,7 +435,7 @@ class _RenderLayoutBuilder extends RenderBox
433
435
@override
434
436
void performLayout () {
435
437
final BoxConstraints constraints = this .constraints;
436
- rebuildIfNecessary ();
438
+ runLayoutCallback ();
437
439
if (child != null ) {
438
440
child! .layout (constraints, parentUsesSize: true );
439
441
size = constraints.constrain (child! .size);
0 commit comments