Unverified Commit 7625c10f authored by Polina Cherkasova's avatar Polina Cherkasova Committed by GitHub

_MaterialAppState should dispose MaterialHeroController. (#133951)

parent af1b7494
......@@ -880,6 +880,12 @@ class _MaterialAppState extends State<MaterialApp> {
_heroController = MaterialApp.createMaterialHeroController();
}
@override
void dispose() {
_heroController.dispose();
super.dispose();
}
// Combine the Localizations for Material with the ones contributed
// by the localizationsDelegates parameter, if any. Only the first delegate
// of a particular LocalizationsDelegate.type is loaded so the
......
......@@ -612,6 +612,19 @@ class _HeroFlight {
navigator.userGestureInProgressNotifier.addListener(delayedPerformAnimationUpdate);
}
/// Releases resources.
@mustCallSuper
void dispose() {
if (overlayEntry != null) {
overlayEntry!.remove();
overlayEntry!.dispose();
overlayEntry = null;
_proxyAnimation.parent = null;
_proxyAnimation.removeListener(onTick);
_proxyAnimation.removeStatusListener(_handleAnimationUpdate);
}
}
void onTick() {
final RenderBox? toHeroBox = (!_aborted && manifest.toHero.mounted)
? manifest.toHero.context.findRenderObject() as RenderBox?
......@@ -1027,6 +1040,14 @@ class HeroController extends NavigatorObserver {
},
);
}
/// Releases resources.
@mustCallSuper
void dispose() {
for (final _HeroFlight flight in _flights.values) {
flight.dispose();
}
}
}
/// Enables or disables [Hero]es in the widget subtree.
......
......@@ -14,6 +14,7 @@ import 'package:flutter/foundation.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';
void main() {
testWidgets('SnackBar control test', (WidgetTester tester) async {
......@@ -2542,7 +2543,9 @@ void main() {
expect(find.text(secondHeader), findsOneWidget);
});
testWidgets('Should have only one SnackBar during back swipe navigation', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Should have only one SnackBar during back swipe navigation',
leakTrackingTestConfig: LeakTrackingTestConfig.debugNotDisposed(),
(WidgetTester tester) async {
const String snackBarText = 'hello snackbar';
const Key snackTarget = Key('snack-target');
const Key transitionTarget = Key('transition-target');
......
......@@ -5,9 +5,10 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() {
testWidgets('Material3 has sentence case labels', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Material3 has sentence case labels', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(useMaterial3: true),
......@@ -38,7 +39,7 @@ void main() {
expect(find.text('Cancel'), findsWidgets);
});
testWidgets('Stepper tap callback test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper tap callback test', (WidgetTester tester) async {
int index = 0;
await tester.pumpWidget(
......@@ -72,7 +73,7 @@ void main() {
expect(index, 1);
});
testWidgets('Stepper expansion test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper expansion test', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Center(
......@@ -139,7 +140,7 @@ void main() {
expect(box.size.height, 432.0);
});
testWidgets('Stepper horizontal size test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper horizontal size test', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Center(
......@@ -165,7 +166,7 @@ void main() {
expect(box.size.height, 600.0);
});
testWidgets('Stepper visibility test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper visibility test', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Material(
......@@ -214,7 +215,7 @@ void main() {
expect(find.text('B'), findsOneWidget);
});
testWidgets('Material2 - Stepper button test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Material2 - Stepper button test', (WidgetTester tester) async {
bool continuePressed = false;
bool cancelPressed = false;
......@@ -258,7 +259,7 @@ void main() {
expect(cancelPressed, isTrue);
});
testWidgets('Material3 - Stepper button test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Material3 - Stepper button test', (WidgetTester tester) async {
bool continuePressed = false;
bool cancelPressed = false;
......@@ -302,7 +303,7 @@ void main() {
expect(cancelPressed, isTrue);
});
testWidgets('Stepper disabled step test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper disabled step test', (WidgetTester tester) async {
int index = 0;
await tester.pumpWidget(
......@@ -338,7 +339,7 @@ void main() {
expect(index, 0);
});
testWidgets('Stepper scroll test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper scroll test', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Material(
......@@ -412,7 +413,7 @@ void main() {
expect(scrollableState.position.pixels, greaterThan(0.0));
});
testWidgets('Stepper index test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper index test', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Center(
......@@ -445,7 +446,7 @@ void main() {
expect(find.text('2'), findsOneWidget);
});
testWidgets('Stepper custom controls test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper custom controls test', (WidgetTester tester) async {
bool continuePressed = false;
void setContinue() {
continuePressed = true;
......@@ -524,7 +525,7 @@ void main() {
expect(continuePressed, isTrue);
});
testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper custom indexed controls test', (WidgetTester tester) async {
int currentStep = 0;
void setContinue() {
......@@ -619,7 +620,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
expect(find.text('Continue to 2'), findsNWidgets(1));
});
testWidgets('Stepper error test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper error test', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Center(
......@@ -644,7 +645,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
expect(find.text('!'), findsOneWidget);
});
testWidgets('Nested stepper error test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Nested stepper error test', (WidgetTester tester) async {
late FlutterErrorDetails errorDetails;
final FlutterExceptionHandler? oldHandler = FlutterError.onError;
FlutterError.onError = (FlutterErrorDetails details) {
......@@ -711,7 +712,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
});
///https://github.com/flutter/flutter/issues/16920
testWidgets('Stepper icons size test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper icons size test', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Material(
......@@ -740,7 +741,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
expect(renderObject.size, equals(const Size.square(18.0)));
});
testWidgets('Stepper physics scroll error test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper physics scroll error test', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Material(
......@@ -773,7 +774,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
expect(find.text('Text After Stepper'), findsNothing);
});
testWidgets("Vertical Stepper can't be focused when disabled.", (WidgetTester tester) async {
testWidgetsWithLeakTracking("Vertical Stepper can't be focused when disabled.", (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Material(
......@@ -797,7 +798,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
expect(disabledNode.hasPrimaryFocus, isFalse);
});
testWidgets("Horizontal Stepper can't be focused when disabled.", (WidgetTester tester) async {
testWidgetsWithLeakTracking("Horizontal Stepper can't be focused when disabled.", (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Material(
......@@ -822,7 +823,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
expect(disabledNode.hasPrimaryFocus, isFalse);
});
testWidgets('Stepper header title should not overflow', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper header title should not overflow', (WidgetTester tester) async {
const String longText =
'A long long long long long long long long long long long long text';
......@@ -848,7 +849,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
expect(tester.takeException(), isNull);
});
testWidgets('Stepper header subtitle should not overflow', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper header subtitle should not overflow', (WidgetTester tester) async {
const String longText =
'A long long long long long long long long long long long long text';
......@@ -875,7 +876,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
expect(tester.takeException(), isNull);
});
testWidgets('Material2 - Stepper enabled button styles', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Material2 - Stepper enabled button styles', (WidgetTester tester) async {
Widget buildFrame(ThemeData theme) {
return MaterialApp(
theme: theme,
......@@ -935,7 +936,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
expect(tester.getRect(find.widgetWithText(TextButton, cancelStr)), cancelButtonRect);
});
testWidgets('Material3 - Stepper enabled button styles', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Material3 - Stepper enabled button styles', (WidgetTester tester) async {
Widget buildFrame(ThemeData theme) {
return MaterialApp(
theme: theme,
......@@ -1007,7 +1008,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
);
});
testWidgets('Material2 - Stepper disabled button styles', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Material2 - Stepper disabled button styles', (WidgetTester tester) async {
Widget buildFrame(ThemeData theme) {
return MaterialApp(
theme: theme,
......@@ -1053,7 +1054,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
expect(buttonMaterial(cancelStr).textStyle!.color!.value, 0x61ffffff);
});
testWidgets('Material3 - Stepper disabled button styles', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Material3 - Stepper disabled button styles', (WidgetTester tester) async {
Widget buildFrame(ThemeData theme) {
return MaterialApp(
theme: theme,
......@@ -1113,7 +1114,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
);
});
testWidgets('Vertical and Horizontal Stepper physics test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Vertical and Horizontal Stepper physics test', (WidgetTester tester) async {
const ScrollPhysics physics = NeverScrollableScrollPhysics();
for (final StepperType type in StepperType.values) {
......@@ -1142,38 +1143,39 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
}
});
testWidgets('ScrollController is passed to the stepper listview', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
for (final StepperType type in StepperType.values) {
await tester.pumpWidget(
MaterialApp(
home: Material(
child: Stepper(
controller: controller,
type: type,
steps: const <Step>[
Step(
title: Text('Step 1'),
content: SizedBox(
width: 100.0,
height: 100.0,
),
testWidgetsWithLeakTracking('ScrollController is passed to the stepper listview', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(() => controller.dispose());
for (final StepperType type in StepperType.values) {
await tester.pumpWidget(
MaterialApp(
home: Material(
child: Stepper(
controller: controller,
type: type,
steps: const <Step>[
Step(
title: Text('Step 1'),
content: SizedBox(
width: 100.0,
height: 100.0,
),
],
),
),
],
),
),
);
),
);
final ListView listView = tester.widget<ListView>(
find.descendant(of: find.byType(Stepper),
matching: find.byType(ListView),
));
expect(listView.controller, controller);
}
});
final ListView listView = tester.widget<ListView>(
find.descendant(of: find.byType(Stepper),
matching: find.byType(ListView),
));
expect(listView.controller, controller);
}
});
testWidgets('Stepper horizontal size test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper horizontal size test', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/pull/77732
Widget buildFrame({ bool isActive = true, Brightness? brightness }) {
return MaterialApp(
......@@ -1218,7 +1220,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
expect(circleFillColor(), dark.background);
});
testWidgets('Stepper custom elevation', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper custom elevation', (WidgetTester tester) async {
const double elevation = 4.0;
await tester.pumpWidget(
......@@ -1252,7 +1254,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
expect(material.elevation, elevation);
});
testWidgets('Stepper with default elevation', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper with default elevation', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
......@@ -1284,7 +1286,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
expect(material.elevation, 2.0);
});
testWidgets('Stepper horizontal preserves state', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper horizontal preserves state', (WidgetTester tester) async {
const Color untappedColor = Colors.blue;
const Color tappedColor = Colors.red;
int index = 0;
......@@ -1355,7 +1357,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
// The color should still be `tappedColor`
expect(getColor(), tappedColor);
});
testWidgets('Stepper custom margin', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper custom margin', (WidgetTester tester) async {
const EdgeInsetsGeometry margin = EdgeInsetsDirectional.only(
bottom: 20,
......@@ -1392,7 +1394,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
expect(material.margin, equals(margin));
});
testWidgets('Stepper with Alternative Label', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper with Alternative Label', (WidgetTester tester) async {
int index = 0;
late TextStyle bodyLargeStyle;
late TextStyle bodyMediumStyle;
......@@ -1476,7 +1478,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
expect(bodyMediumStyle, nextLabelTextWidget.style);
});
testWidgets('Stepper Connector Style', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper Connector Style', (WidgetTester tester) async {
const Color selectedColor = Colors.black;
const Color disabledColor = Colors.white;
int index = 0;
......@@ -1545,7 +1547,7 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
expect(lineColor('line0'), selectedColor);
});
testWidgets('Stepper stepIconBuilder test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stepper stepIconBuilder test', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Material(
......
......@@ -865,7 +865,7 @@ void main() {
);
});
testWidgets('Material3 - SwitchListTile respects thumbColor in hovered/pressed states', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Material3 - SwitchListTile respects thumbColor in hovered/pressed states', (WidgetTester tester) async {
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
const Color hoveredThumbColor = Color(0xFF4caf50);
const Color pressedThumbColor = Color(0xFFF44336);
......
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