Reverts "Fix memory leak in `TabPageSelector` (#147403)" (#147622)
Reverts: flutter/flutter#147403
Initiated by: chingjun
Reason for reverting: Causing an internal test to fail, see b/338159496 for details
Original PR Author: ValentinVignal
Reviewed By: {polina-c}
This change reverts the following previous change:
Part of https://github.com/flutter/flutter/issues/141198diff --git a/packages/flutter/lib/src/material/tabs.dart b/packages/flutter/lib/src/material/tabs.dart
index 2b001a9..6cb60b3 100644
--- a/packages/flutter/lib/src/material/tabs.dart
+++ b/packages/flutter/lib/src/material/tabs.dart
@@ -2219,7 +2219,7 @@
///
/// If a [TabController] is not provided, then there must be a
/// [DefaultTabController] ancestor.
-class TabPageSelector extends StatefulWidget {
+class TabPageSelector extends StatelessWidget {
/// Creates a compact widget that indicates which tab has been selected.
const TabPageSelector({
super.key,
@@ -2256,73 +2256,6 @@
/// Defaults to [BorderStyle.solid] if value is not specified.
final BorderStyle? borderStyle;
- @override
- State<TabPageSelector> createState() => _TabPageSelectorState();
-}
-
-class _TabPageSelectorState extends State<TabPageSelector> {
- TabController? _previousTabController;
- TabController get _tabController {
- final TabController? tabController = widget.controller ?? DefaultTabController.maybeOf(context);
- assert(() {
- if (tabController == null) {
- throw FlutterError(
- 'No TabController for $runtimeType.\n'
- 'When creating a $runtimeType, you must either provide an explicit TabController '
- 'using the "controller" property, or you must ensure that there is a '
- 'DefaultTabController above the $runtimeType.\n'
- 'In this case, there was neither an explicit controller nor a default controller.',
- );
- }
- return true;
- }());
- return tabController!;
- }
-
- CurvedAnimation? _animation;
-
- @override
- void initState() {
- super.initState();
- _setAnimation();
- }
-
- @override
- void didUpdateWidget (TabPageSelector oldWidget) {
- super.didUpdateWidget(oldWidget);
- if (_previousTabController?.animation != _tabController.animation) {
- _setAnimation();
- }
- if (_previousTabController != _tabController) {
- _previousTabController = _tabController;
- }
- }
-
- @override
- void didChangeDependencies() {
- super.didChangeDependencies();
- if (_previousTabController?.animation != _tabController.animation) {
- _setAnimation();
- }
- if (_previousTabController != _tabController) {
- _previousTabController = _tabController;
- }
- }
-
- void _setAnimation() {
- _animation?.dispose();
- _animation = CurvedAnimation(
- parent: _tabController.animation!,
- curve: Curves.fastOutSlowIn,
- );
- }
-
- @override
- void dispose() {
- _animation?.dispose();
- super.dispose();
- }
-
Widget _buildTabIndicator(
int tabIndex,
TabController tabController,
@@ -2357,27 +2290,44 @@
return TabPageSelectorIndicator(
backgroundColor: background,
borderColor: selectedColorTween.end!,
- size: widget.indicatorSize,
- borderStyle: widget.borderStyle ?? BorderStyle.solid,
+ size: indicatorSize,
+ borderStyle: borderStyle ?? BorderStyle.solid,
);
}
@override
Widget build(BuildContext context) {
- final Color fixColor = widget.color ?? Colors.transparent;
- final Color fixSelectedColor = widget.selectedColor ?? Theme.of(context).colorScheme.secondary;
+ final Color fixColor = color ?? Colors.transparent;
+ final Color fixSelectedColor = selectedColor ?? Theme.of(context).colorScheme.secondary;
final ColorTween selectedColorTween = ColorTween(begin: fixColor, end: fixSelectedColor);
final ColorTween previousColorTween = ColorTween(begin: fixSelectedColor, end: fixColor);
+ final TabController? tabController = controller ?? DefaultTabController.maybeOf(context);
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
+ assert(() {
+ if (tabController == null) {
+ throw FlutterError(
+ 'No TabController for $runtimeType.\n'
+ 'When creating a $runtimeType, you must either provide an explicit TabController '
+ 'using the "controller" property, or you must ensure that there is a '
+ 'DefaultTabController above the $runtimeType.\n'
+ 'In this case, there was neither an explicit controller nor a default controller.',
+ );
+ }
+ return true;
+ }());
+ final Animation<double> animation = CurvedAnimation(
+ parent: tabController!.animation!,
+ curve: Curves.fastOutSlowIn,
+ );
return AnimatedBuilder(
- animation: _animation!,
+ animation: animation,
builder: (BuildContext context, Widget? child) {
return Semantics(
- label: localizations.tabLabel(tabIndex: _tabController.index + 1, tabCount: _tabController.length),
+ label: localizations.tabLabel(tabIndex: tabController.index + 1, tabCount: tabController.length),
child: Row(
mainAxisSize: MainAxisSize.min,
- children: List<Widget>.generate(_tabController.length, (int tabIndex) {
- return _buildTabIndicator(tabIndex, _tabController, selectedColorTween, previousColorTween);
+ children: List<Widget>.generate(tabController.length, (int tabIndex) {
+ return _buildTabIndicator(tabIndex, tabController, selectedColorTween, previousColorTween);
}).toList(),
),
);
diff --git a/packages/flutter/test/material/page_selector_test.dart b/packages/flutter/test/material/page_selector_test.dart
index 9e8721d..8e988ed 100644
--- a/packages/flutter/test/material/page_selector_test.dart
+++ b/packages/flutter/test/material/page_selector_test.dart
@@ -4,7 +4,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
-import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
const Color kSelectedColor = Color(0xFF00FF00);
const Color kUnselectedColor = Colors.transparent;
@@ -87,10 +86,7 @@
expect(indicatorColors(tester), const <Color>[kUnselectedColor, kUnselectedColor, kSelectedColor]);
});
- testWidgets('PageSelector responds correctly to TabController.animateTo()',
- // TODO(polina-c): remove when fixed https://github.com/flutter/flutter/issues/145600 [leak-tracking-opt-in]
- experimentalLeakTesting: LeakTesting.settings.withTracked(classes: const <String>['CurvedAnimation']),
- (WidgetTester tester) async {
+ testWidgets('PageSelector responds correctly to TabController.animateTo()', (WidgetTester tester) async {
final TabController tabController = TabController(
vsync: const TestVSync(),
length: 3,