Do not cache itemBuilder calls in a GridView (#61033)
diff --git a/packages/flutter/lib/src/widgets/sliver.dart b/packages/flutter/lib/src/widgets/sliver.dart
index 40eacdc..32171aa 100644
--- a/packages/flutter/lib/src/widgets/sliver.dart
+++ b/packages/flutter/lib/src/widgets/sliver.dart
@@ -1052,20 +1052,11 @@
performRebuild();
}
- // We inflate widgets at two different times:
- // 1. When we ourselves are told to rebuild (see performRebuild).
- // 2. When our render object needs a new child (see createChild).
- // In both cases, we cache the results of calling into our delegate to get the widget,
- // so that if we do case 2 later, we don't call the builder again.
- // Any time we do case 1, though, we reset the cache.
-
- final Map<int, Widget> _childWidgets = HashMap<int, Widget>();
final SplayTreeMap<int, Element> _childElements = SplayTreeMap<int, Element>();
RenderBox _currentBeforeChild;
@override
void performRebuild() {
- _childWidgets.clear(); // Reset the cache, as described above.
super.performRebuild();
_currentBeforeChild = null;
assert(_currentlyUpdatingChildIndex == null);
@@ -1133,7 +1124,7 @@
}
Widget _build(int index) {
- return _childWidgets.putIfAbsent(index, () => widget.delegate.build(this, index));
+ return widget.delegate.build(this, index);
}
@override
diff --git a/packages/flutter/test/widgets/grid_view_test.dart b/packages/flutter/test/widgets/grid_view_test.dart
index 57baadf..4785c58 100644
--- a/packages/flutter/test/widgets/grid_view_test.dart
+++ b/packages/flutter/test/widgets/grid_view_test.dart
@@ -566,4 +566,40 @@
expect(tester.getTopLeft(find.byKey(target)), const Offset(606.0, 0.0));
expect(tester.getBottomRight(find.byKey(target)), const Offset(800.0, 194.0));
});
+
+ testWidgets('GridView does not cache itemBuilder calls', (WidgetTester tester) async {
+ final Map<int, int> counters = <int, int>{};
+
+ await tester.pumpWidget(Directionality(
+ textDirection: TextDirection.ltr,
+ child: GridView.builder(
+ itemCount: 1000,
+ gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
+ itemBuilder: (BuildContext context, int index) {
+ counters[index] ??= 0;
+ counters[index] += 1;
+ return SizedBox(
+ key: ValueKey<int>(index),
+ width: 200,
+ height: 200,
+ );
+ },
+ ),
+ ));
+
+ expect(find.byKey(const ValueKey<int>(4)), findsOneWidget);
+ expect(counters[4], 1);
+
+ await tester.fling(find.byType(GridView), const Offset(0, -300), 5000);
+ await tester.pumpAndSettle();
+
+ expect(find.byKey(const ValueKey<int>(4)), findsNothing);
+ expect(counters[4], 1);
+
+ await tester.fling(find.byType(GridView), const Offset(0, 300), 5000);
+ await tester.pumpAndSettle();
+
+ expect(find.byKey(const ValueKey<int>(4)), findsOneWidget);
+ expect(counters[4], 2);
+ });
}