From 3882afbfa997d16bd59f8088d58ccf8d21c65617 Mon Sep 17 00:00:00 2001 From: Valentin Vignal <32538273+ValentinVignal@users.noreply.github.com> Date: Wed, 17 Apr 2024 03:15:37 +0800 Subject: [PATCH] Fix leak memory in `Tooltip` and account detail (#146833) --- packages/flutter/lib/src/material/tooltip.dart | 10 +++++++++- .../lib/src/material/user_accounts_drawer_header.dart | 5 +++-- packages/flutter/test/material/filter_chip_test.dart | 6 +++++- packages/flutter/test/material/input_chip_test.dart | 6 +++++- .../material/user_accounts_drawer_header_test.dart | 6 +++++- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/packages/flutter/lib/src/material/tooltip.dart b/packages/flutter/lib/src/material/tooltip.dart index 4431019283d..1456e0d278d 100644 --- a/packages/flutter/lib/src/material/tooltip.dart +++ b/packages/flutter/lib/src/material/tooltip.dart @@ -455,6 +455,13 @@ class TooltipState extends State with SingleTickerProviderStateMixin { vsync: this, )..addStatusListener(_handleStatusChanged); } + CurvedAnimation? _backingOverlayAnimation; + CurvedAnimation get _overlayAnimation { + return _backingOverlayAnimation ??= CurvedAnimation( + parent: _controller, + curve: Curves.fastOutSlowIn, + ); + } LongPressGestureRecognizer? _longPressRecognizer; TapGestureRecognizer? _tapRecognizer; @@ -796,7 +803,7 @@ class TooltipState extends State with SingleTickerProviderStateMixin { decoration: widget.decoration ?? tooltipTheme.decoration ?? defaultDecoration, textStyle: widget.textStyle ?? tooltipTheme.textStyle ?? defaultTextStyle, textAlign: widget.textAlign ?? tooltipTheme.textAlign ?? _defaultTextAlign, - animation: CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn), + animation:_overlayAnimation, target: target, verticalOffset: widget.verticalOffset ?? tooltipTheme.verticalOffset ?? _defaultVerticalOffset, preferBelow: widget.preferBelow ?? tooltipTheme.preferBelow ?? _defaultPreferBelow, @@ -821,6 +828,7 @@ class TooltipState extends State with SingleTickerProviderStateMixin { _tapRecognizer?.dispose(); _timer?.cancel(); _backingController?.dispose(); + _backingOverlayAnimation?.dispose(); super.dispose(); } diff --git a/packages/flutter/lib/src/material/user_accounts_drawer_header.dart b/packages/flutter/lib/src/material/user_accounts_drawer_header.dart index 7550a00e1cb..60aee2c0a5b 100644 --- a/packages/flutter/lib/src/material/user_accounts_drawer_header.dart +++ b/packages/flutter/lib/src/material/user_accounts_drawer_header.dart @@ -87,8 +87,8 @@ class _AccountDetails extends StatefulWidget { } class _AccountDetailsState extends State<_AccountDetails> with SingleTickerProviderStateMixin { - late Animation _animation; - late AnimationController _controller; + late final CurvedAnimation _animation; + late final AnimationController _controller; @override void initState () { super.initState(); @@ -110,6 +110,7 @@ class _AccountDetailsState extends State<_AccountDetails> with SingleTickerProvi @override void dispose() { _controller.dispose(); + _animation.dispose(); super.dispose(); } diff --git a/packages/flutter/test/material/filter_chip_test.dart b/packages/flutter/test/material/filter_chip_test.dart index 535879c94fa..1fadbe152a0 100644 --- a/packages/flutter/test/material/filter_chip_test.dart +++ b/packages/flutter/test/material/filter_chip_test.dart @@ -11,6 +11,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; import 'feedback_tester.dart'; @@ -956,7 +957,10 @@ void main() { expect(getIconData(tester).color, theme.iconTheme.color?.withAlpha(0xde)); }); - testWidgets('Customize FilterChip delete button', (WidgetTester tester) async { + testWidgets('Customize FilterChip delete button', + // TODO(polina-c): remove when fixed https://github.com/flutter/flutter/issues/145600 [leak-tracking-opt-in] + experimentalLeakTesting: LeakTesting.settings.withTracked(classes: const ['CurvedAnimation']), + (WidgetTester tester) async { Widget buildChip({ Widget? deleteIcon, Color? deleteIconColor, diff --git a/packages/flutter/test/material/input_chip_test.dart b/packages/flutter/test/material/input_chip_test.dart index e692602668a..0889f9d301c 100644 --- a/packages/flutter/test/material/input_chip_test.dart +++ b/packages/flutter/test/material/input_chip_test.dart @@ -10,6 +10,7 @@ library; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; /// Adds the basic requirements for a Chip. Widget wrapForChip({ @@ -456,7 +457,10 @@ void main() { await expectLater(find.byType(RawChip), matchesGoldenFile('input_chip.disabled.delete_button.png')); }); - testWidgets('Delete button tooltip is not shown on disabled InputChip', (WidgetTester tester) async { + testWidgets('Delete button tooltip is not shown on disabled InputChip', + // TODO(polina-c): remove when fixed https://github.com/flutter/flutter/issues/145600 [leak-tracking-opt-in] + experimentalLeakTesting: LeakTesting.settings.withTracked(classes: const ['CurvedAnimation']), + (WidgetTester tester) async { Widget buildChip({ bool enabled = true }) { return wrapForChip( child: InputChip( diff --git a/packages/flutter/test/material/user_accounts_drawer_header_test.dart b/packages/flutter/test/material/user_accounts_drawer_header_test.dart index a106eaabf8f..45d511af2ec 100644 --- a/packages/flutter/test/material/user_accounts_drawer_header_test.dart +++ b/packages/flutter/test/material/user_accounts_drawer_header_test.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; import '../widgets/semantics_tester.dart'; const Key avatarA = Key('A'); @@ -261,7 +262,10 @@ void main() { expect(transformWidget.transform.getRotation()[4], 1.0); }); - testWidgets('UserAccountsDrawerHeader icon color changes', (WidgetTester tester) async { + testWidgets('UserAccountsDrawerHeader icon color changes', + // TODO(polina-c): remove when fixed https://github.com/flutter/flutter/issues/145600 [leak-tracking-opt-in] + experimentalLeakTesting: LeakTesting.settings.withTracked(classes: const ['CurvedAnimation']), + (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( home: Material( child: UserAccountsDrawerHeader(