Skip to content

Commit f97978f

Browse files
authored
Re-use methods to calculate leading and trailing garbage in RenderSliverMultiBoxAdaptor (#143884)
My RenderSliverMultiBoxAdaptor/RenderSliverFixedExtentList/RenderSliverVariedExtentList yak shave continues. I've been subclassing RenderSliverVariedExtentList for SliverTree and have found some opportunities for clean up. There is a larger clean up I'd like to do, but this week SliverTree comes first. I noticed these methods were getting repeated �, and I was about to repeat them again � for the tree, so I figured bumping them up to the base class was better than continuing to copy-paste the same methods.
1 parent c3e786f commit f97978f

File tree

4 files changed

+76
-44
lines changed

4 files changed

+76
-44
lines changed

packages/flutter/lib/src/rendering/sliver_fixed_extent_list.dart

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -236,26 +236,6 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda
236236
}
237237
}
238238

239-
int _calculateLeadingGarbage(int firstIndex) {
240-
RenderBox? walker = firstChild;
241-
int leadingGarbage = 0;
242-
while (walker != null && indexOf(walker) < firstIndex) {
243-
leadingGarbage += 1;
244-
walker = childAfter(walker);
245-
}
246-
return leadingGarbage;
247-
}
248-
249-
int _calculateTrailingGarbage(int targetLastIndex) {
250-
RenderBox? walker = lastChild;
251-
int trailingGarbage = 0;
252-
while (walker != null && indexOf(walker) > targetLastIndex) {
253-
trailingGarbage += 1;
254-
walker = childBefore(walker);
255-
}
256-
return trailingGarbage;
257-
}
258-
259239
int _getChildIndexForScrollOffset(double scrollOffset, ItemExtentBuilder callback) {
260240
if (scrollOffset == 0.0) {
261241
return 0;
@@ -323,8 +303,8 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda
323303
getMaxChildIndexForScrollOffset(targetEndScrollOffset, deprecatedExtraItemExtent) : null;
324304

325305
if (firstChild != null) {
326-
final int leadingGarbage = _calculateLeadingGarbage(firstIndex);
327-
final int trailingGarbage = targetLastIndex != null ? _calculateTrailingGarbage(targetLastIndex) : 0;
306+
final int leadingGarbage = calculateLeadingGarbage(firstIndex: firstIndex);
307+
final int trailingGarbage = targetLastIndex != null ? calculateTrailingGarbage(lastIndex: targetLastIndex) : 0;
328308
collectGarbage(leadingGarbage, trailingGarbage);
329309
} else {
330310
collectGarbage(0, 0);

packages/flutter/lib/src/rendering/sliver_grid.dart

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -597,8 +597,8 @@ class RenderSliverGrid extends RenderSliverMultiBoxAdaptor {
597597
final int? targetLastIndex = targetEndScrollOffset.isFinite ?
598598
layout.getMaxChildIndexForScrollOffset(targetEndScrollOffset) : null;
599599
if (firstChild != null) {
600-
final int leadingGarbage = _calculateLeadingGarbage(firstIndex);
601-
final int trailingGarbage = targetLastIndex != null ? _calculateTrailingGarbage(targetLastIndex) : 0;
600+
final int leadingGarbage = calculateLeadingGarbage(firstIndex: firstIndex);
601+
final int trailingGarbage = targetLastIndex != null ? calculateTrailingGarbage(lastIndex: targetLastIndex) : 0;
602602
collectGarbage(leadingGarbage, trailingGarbage);
603603
} else {
604604
collectGarbage(0, 0);
@@ -708,24 +708,4 @@ class RenderSliverGrid extends RenderSliverMultiBoxAdaptor {
708708
}
709709
childManager.didFinishLayout();
710710
}
711-
712-
int _calculateLeadingGarbage(int firstIndex) {
713-
RenderBox? walker = firstChild;
714-
int leadingGarbage = 0;
715-
while (walker != null && indexOf(walker) < firstIndex) {
716-
leadingGarbage += 1;
717-
walker = childAfter(walker);
718-
}
719-
return leadingGarbage;
720-
}
721-
722-
int _calculateTrailingGarbage(int targetLastIndex) {
723-
RenderBox? walker = lastChild;
724-
int trailingGarbage = 0;
725-
while (walker != null && indexOf(walker) > targetLastIndex) {
726-
trailingGarbage += 1;
727-
walker = childBefore(walker);
728-
}
729-
return trailingGarbage;
730-
}
731711
}

packages/flutter/lib/src/rendering/sliver_multi_box_adaptor.dart

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,48 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
504504
return null;
505505
}
506506

507+
/// Returns the number of children preceding the `firstIndex` that need to be
508+
/// garbage collected.
509+
///
510+
/// See also:
511+
///
512+
/// * [collectGarbage], which takes the leading and trailing number of
513+
/// children to be garbage collected.
514+
/// * [calculateTrailingGarbage], which similarly returns the number of
515+
/// trailing children to be garbage collected.
516+
@visibleForTesting
517+
@protected
518+
int calculateLeadingGarbage({required int firstIndex}) {
519+
RenderBox? walker = firstChild;
520+
int leadingGarbage = 0;
521+
while (walker != null && indexOf(walker) < firstIndex) {
522+
leadingGarbage += 1;
523+
walker = childAfter(walker);
524+
}
525+
return leadingGarbage;
526+
}
527+
528+
/// Returns the number of children following the `lastIndex` that need to be
529+
/// garbage collected.
530+
///
531+
/// See also:
532+
///
533+
/// * [collectGarbage], which takes the leading and trailing number of
534+
/// children to be garbage collected.
535+
/// * [calculateLeadingGarbage], which similarly returns the number of
536+
/// leading children to be garbage collected.
537+
@visibleForTesting
538+
@protected
539+
int calculateTrailingGarbage({required int lastIndex}) {
540+
RenderBox? walker = lastChild;
541+
int trailingGarbage = 0;
542+
while (walker != null && indexOf(walker) > lastIndex) {
543+
trailingGarbage += 1;
544+
walker = childBefore(walker);
545+
}
546+
return trailingGarbage;
547+
}
548+
507549
/// Called after layout with the number of children that can be garbage
508550
/// collected at the head and tail of the child list.
509551
///
@@ -513,6 +555,13 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
513555
/// This method also collects any children that were previously kept alive but
514556
/// are now no longer necessary. As such, it should be called every time
515557
/// [performLayout] is run, even if the arguments are both zero.
558+
///
559+
/// See also:
560+
///
561+
/// * [calculateLeadingGarbage], which can be used to determine
562+
/// `leadingGarbage` here.
563+
/// * [calculateTrailingGarbage], which can be used to determine
564+
/// `trailingGarbage` here.
516565
@protected
517566
void collectGarbage(int leadingGarbage, int trailingGarbage) {
518567
assert(_debugAssertChildListLocked());

packages/flutter/test/rendering/sliver_fixed_extent_layout_test.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,29 @@ void main() {
346346
);
347347
expect(maxScrollOffset, 90.0);
348348
});
349+
350+
test('RenderSliverMultiBoxAdaptor has calculate leading and trailing garbage', () {
351+
final List<RenderBox> children = <RenderBox>[
352+
RenderSizedBox(const Size(400.0, 100.0)),
353+
RenderSizedBox(const Size(400.0, 100.0)),
354+
RenderSizedBox(const Size(400.0, 100.0)),
355+
];
356+
final TestRenderSliverBoxChildManager childManager = TestRenderSliverBoxChildManager(
357+
children: children,
358+
);
359+
final RenderSliverFixedExtentList sliver = childManager.createRenderSliverFixedExtentList(30.0);
360+
final RenderViewport root = RenderViewport(
361+
crossAxisDirection: AxisDirection.right,
362+
offset: ViewportOffset.zero(),
363+
cacheExtent: 100,
364+
children: <RenderSliver>[ sliver ],
365+
);
366+
layout(root);
367+
// There are 3 children. If I want to garbage collect based on keeping only
368+
// the middle child, then I should get 1 for leading and 1 for trailing.
369+
expect(sliver.calculateLeadingGarbage(firstIndex: 1), 1);
370+
expect(sliver.calculateTrailingGarbage(lastIndex: 1), 1);
371+
});
349372
}
350373

351374
int testGetMaxChildIndexForScrollOffset(double scrollOffset, double itemExtent) {

0 commit comments

Comments
 (0)