Unverified Commit f97978f9 authored by Kate Lovett's avatar Kate Lovett Committed by GitHub

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.
parent c3e786f3
...@@ -236,26 +236,6 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda ...@@ -236,26 +236,6 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda
} }
} }
int _calculateLeadingGarbage(int firstIndex) {
RenderBox? walker = firstChild;
int leadingGarbage = 0;
while (walker != null && indexOf(walker) < firstIndex) {
leadingGarbage += 1;
walker = childAfter(walker);
}
return leadingGarbage;
}
int _calculateTrailingGarbage(int targetLastIndex) {
RenderBox? walker = lastChild;
int trailingGarbage = 0;
while (walker != null && indexOf(walker) > targetLastIndex) {
trailingGarbage += 1;
walker = childBefore(walker);
}
return trailingGarbage;
}
int _getChildIndexForScrollOffset(double scrollOffset, ItemExtentBuilder callback) { int _getChildIndexForScrollOffset(double scrollOffset, ItemExtentBuilder callback) {
if (scrollOffset == 0.0) { if (scrollOffset == 0.0) {
return 0; return 0;
...@@ -323,8 +303,8 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda ...@@ -323,8 +303,8 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda
getMaxChildIndexForScrollOffset(targetEndScrollOffset, deprecatedExtraItemExtent) : null; getMaxChildIndexForScrollOffset(targetEndScrollOffset, deprecatedExtraItemExtent) : null;
if (firstChild != null) { if (firstChild != null) {
final int leadingGarbage = _calculateLeadingGarbage(firstIndex); final int leadingGarbage = calculateLeadingGarbage(firstIndex: firstIndex);
final int trailingGarbage = targetLastIndex != null ? _calculateTrailingGarbage(targetLastIndex) : 0; final int trailingGarbage = targetLastIndex != null ? calculateTrailingGarbage(lastIndex: targetLastIndex) : 0;
collectGarbage(leadingGarbage, trailingGarbage); collectGarbage(leadingGarbage, trailingGarbage);
} else { } else {
collectGarbage(0, 0); collectGarbage(0, 0);
......
...@@ -597,8 +597,8 @@ class RenderSliverGrid extends RenderSliverMultiBoxAdaptor { ...@@ -597,8 +597,8 @@ class RenderSliverGrid extends RenderSliverMultiBoxAdaptor {
final int? targetLastIndex = targetEndScrollOffset.isFinite ? final int? targetLastIndex = targetEndScrollOffset.isFinite ?
layout.getMaxChildIndexForScrollOffset(targetEndScrollOffset) : null; layout.getMaxChildIndexForScrollOffset(targetEndScrollOffset) : null;
if (firstChild != null) { if (firstChild != null) {
final int leadingGarbage = _calculateLeadingGarbage(firstIndex); final int leadingGarbage = calculateLeadingGarbage(firstIndex: firstIndex);
final int trailingGarbage = targetLastIndex != null ? _calculateTrailingGarbage(targetLastIndex) : 0; final int trailingGarbage = targetLastIndex != null ? calculateTrailingGarbage(lastIndex: targetLastIndex) : 0;
collectGarbage(leadingGarbage, trailingGarbage); collectGarbage(leadingGarbage, trailingGarbage);
} else { } else {
collectGarbage(0, 0); collectGarbage(0, 0);
...@@ -708,24 +708,4 @@ class RenderSliverGrid extends RenderSliverMultiBoxAdaptor { ...@@ -708,24 +708,4 @@ class RenderSliverGrid extends RenderSliverMultiBoxAdaptor {
} }
childManager.didFinishLayout(); childManager.didFinishLayout();
} }
int _calculateLeadingGarbage(int firstIndex) {
RenderBox? walker = firstChild;
int leadingGarbage = 0;
while (walker != null && indexOf(walker) < firstIndex) {
leadingGarbage += 1;
walker = childAfter(walker);
}
return leadingGarbage;
}
int _calculateTrailingGarbage(int targetLastIndex) {
RenderBox? walker = lastChild;
int trailingGarbage = 0;
while (walker != null && indexOf(walker) > targetLastIndex) {
trailingGarbage += 1;
walker = childBefore(walker);
}
return trailingGarbage;
}
} }
...@@ -504,6 +504,48 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver ...@@ -504,6 +504,48 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
return null; return null;
} }
/// Returns the number of children preceding the `firstIndex` that need to be
/// garbage collected.
///
/// See also:
///
/// * [collectGarbage], which takes the leading and trailing number of
/// children to be garbage collected.
/// * [calculateTrailingGarbage], which similarly returns the number of
/// trailing children to be garbage collected.
@visibleForTesting
@protected
int calculateLeadingGarbage({required int firstIndex}) {
RenderBox? walker = firstChild;
int leadingGarbage = 0;
while (walker != null && indexOf(walker) < firstIndex) {
leadingGarbage += 1;
walker = childAfter(walker);
}
return leadingGarbage;
}
/// Returns the number of children following the `lastIndex` that need to be
/// garbage collected.
///
/// See also:
///
/// * [collectGarbage], which takes the leading and trailing number of
/// children to be garbage collected.
/// * [calculateLeadingGarbage], which similarly returns the number of
/// leading children to be garbage collected.
@visibleForTesting
@protected
int calculateTrailingGarbage({required int lastIndex}) {
RenderBox? walker = lastChild;
int trailingGarbage = 0;
while (walker != null && indexOf(walker) > lastIndex) {
trailingGarbage += 1;
walker = childBefore(walker);
}
return trailingGarbage;
}
/// Called after layout with the number of children that can be garbage /// Called after layout with the number of children that can be garbage
/// collected at the head and tail of the child list. /// collected at the head and tail of the child list.
/// ///
...@@ -513,6 +555,13 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver ...@@ -513,6 +555,13 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
/// This method also collects any children that were previously kept alive but /// This method also collects any children that were previously kept alive but
/// are now no longer necessary. As such, it should be called every time /// are now no longer necessary. As such, it should be called every time
/// [performLayout] is run, even if the arguments are both zero. /// [performLayout] is run, even if the arguments are both zero.
///
/// See also:
///
/// * [calculateLeadingGarbage], which can be used to determine
/// `leadingGarbage` here.
/// * [calculateTrailingGarbage], which can be used to determine
/// `trailingGarbage` here.
@protected @protected
void collectGarbage(int leadingGarbage, int trailingGarbage) { void collectGarbage(int leadingGarbage, int trailingGarbage) {
assert(_debugAssertChildListLocked()); assert(_debugAssertChildListLocked());
......
...@@ -346,6 +346,29 @@ void main() { ...@@ -346,6 +346,29 @@ void main() {
); );
expect(maxScrollOffset, 90.0); expect(maxScrollOffset, 90.0);
}); });
test('RenderSliverMultiBoxAdaptor has calculate leading and trailing garbage', () {
final List<RenderBox> children = <RenderBox>[
RenderSizedBox(const Size(400.0, 100.0)),
RenderSizedBox(const Size(400.0, 100.0)),
RenderSizedBox(const Size(400.0, 100.0)),
];
final TestRenderSliverBoxChildManager childManager = TestRenderSliverBoxChildManager(
children: children,
);
final RenderSliverFixedExtentList sliver = childManager.createRenderSliverFixedExtentList(30.0);
final RenderViewport root = RenderViewport(
crossAxisDirection: AxisDirection.right,
offset: ViewportOffset.zero(),
cacheExtent: 100,
children: <RenderSliver>[ sliver ],
);
layout(root);
// There are 3 children. If I want to garbage collect based on keeping only
// the middle child, then I should get 1 for leading and 1 for trailing.
expect(sliver.calculateLeadingGarbage(firstIndex: 1), 1);
expect(sliver.calculateTrailingGarbage(lastIndex: 1), 1);
});
} }
int testGetMaxChildIndexForScrollOffset(double scrollOffset, double itemExtent) { int testGetMaxChildIndexForScrollOffset(double scrollOffset, double itemExtent) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment