From 8b129b9b8917803841517438b95732234fd03679 Mon Sep 17 00:00:00 2001 From: Valentin Vignal <32538273+ValentinVignal@users.noreply.github.com> Date: Thu, 16 May 2024 04:50:03 +0800 Subject: [PATCH] Fix memory leaks in `_PopupMenuRoute` (#148373) --- packages/flutter/lib/src/material/popup_menu.dart | 10 +++++++++- packages/flutter/test/material/popup_menu_test.dart | 6 +++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/flutter/lib/src/material/popup_menu.dart b/packages/flutter/lib/src/material/popup_menu.dart index 87409aa1a1e..d16e0aacfba 100644 --- a/packages/flutter/lib/src/material/popup_menu.dart +++ b/packages/flutter/lib/src/material/popup_menu.dart @@ -880,10 +880,12 @@ class _PopupMenuRoute extends PopupRoute { final Clip clipBehavior; final AnimationStyle? popUpAnimationStyle; + CurvedAnimation? _animation; + @override Animation createAnimation() { if (popUpAnimationStyle != AnimationStyle.noAnimation) { - return CurvedAnimation( + return _animation ??= CurvedAnimation( parent: super.createAnimation(), curve: popUpAnimationStyle?.curve ?? Curves.linear, reverseCurve: popUpAnimationStyle?.reverseCurve ?? const Interval(0.0, _kMenuCloseIntervalEnd), @@ -962,6 +964,12 @@ class _PopupMenuRoute extends PopupRoute { Set _avoidBounds(MediaQueryData mediaQuery) { return DisplayFeatureSubScreen.avoidBounds(mediaQuery).toSet(); } + + @override + void dispose() { + _animation?.dispose(); + super.dispose(); + } } /// Show a popup menu that contains the `items` at `position`. diff --git a/packages/flutter/test/material/popup_menu_test.dart b/packages/flutter/test/material/popup_menu_test.dart index aa7fac56122..f53d11da200 100644 --- a/packages/flutter/test/material/popup_menu_test.dart +++ b/packages/flutter/test/material/popup_menu_test.dart @@ -9,6 +9,7 @@ import 'package:flutter/gestures.dart'; 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'; import 'feedback_tester.dart'; @@ -2096,7 +2097,10 @@ void main() { expect(find.text('PopupMenuButton icon'), findsOneWidget); }); - testWidgets('showMenu uses nested navigator by default', (WidgetTester tester) async { + testWidgets('showMenu uses nested navigator by default', + // 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 { final MenuObserver rootObserver = MenuObserver(); final MenuObserver nestedObserver = MenuObserver();