Fix memory leaks in Hero widget (#147303)
This commit is contained in:
@@ -425,7 +425,6 @@ class _HeroState extends State<Hero> {
|
||||
}
|
||||
|
||||
// Everything known about a hero flight that's to be started or diverted.
|
||||
@immutable
|
||||
class _HeroFlightManifest {
|
||||
_HeroFlightManifest({
|
||||
required this.type,
|
||||
@@ -455,8 +454,10 @@ class _HeroFlightManifest {
|
||||
|
||||
Object get tag => fromHero.widget.tag;
|
||||
|
||||
CurvedAnimation? _animation;
|
||||
|
||||
Animation<double> get animation {
|
||||
return CurvedAnimation(
|
||||
return _animation ??= CurvedAnimation(
|
||||
parent: (type == HeroFlightDirection.push) ? toRoute.animation! : fromRoute.animation!,
|
||||
curve: Curves.fastOutSlowIn,
|
||||
reverseCurve: isDiverted ? null : Curves.fastOutSlowIn.flipped,
|
||||
@@ -505,6 +506,11 @@ class _HeroFlightManifest {
|
||||
return '_HeroFlightManifest($type tag: $tag from route: ${fromRoute.settings} '
|
||||
'to route: ${toRoute.settings} with hero: $fromHero to $toHero)${isValid ? '' : ', INVALID'}';
|
||||
}
|
||||
|
||||
@mustCallSuper
|
||||
void dispose() {
|
||||
_animation?.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// Builds the in-flight hero widget.
|
||||
@@ -531,7 +537,13 @@ class _HeroFlight {
|
||||
late ProxyAnimation _proxyAnimation;
|
||||
// The manifest will be available once `start` is called, throughout the
|
||||
// flight's lifecycle.
|
||||
late _HeroFlightManifest manifest;
|
||||
_HeroFlightManifest? _manifest;
|
||||
_HeroFlightManifest get manifest => _manifest!;
|
||||
set manifest (_HeroFlightManifest value) {
|
||||
_manifest?.dispose();
|
||||
_manifest = value;
|
||||
}
|
||||
|
||||
OverlayEntry? overlayEntry;
|
||||
bool _aborted = false;
|
||||
|
||||
@@ -634,6 +646,7 @@ class _HeroFlight {
|
||||
_proxyAnimation.removeListener(onTick);
|
||||
_proxyAnimation.removeStatusListener(_handleAnimationUpdate);
|
||||
}
|
||||
_manifest?.dispose();
|
||||
}
|
||||
|
||||
void onTick() {
|
||||
|
||||
@@ -301,7 +301,10 @@ Future<void> main() async {
|
||||
expect(find.byKey(thirdKey), isInCard);
|
||||
});
|
||||
|
||||
testWidgets('Heroes still animate after hero controller is swapped.', (WidgetTester tester) async {
|
||||
testWidgets('Heroes still animate after hero controller is swapped.',
|
||||
// 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 {
|
||||
final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
|
||||
final UniqueKey heroKey = UniqueKey();
|
||||
final HeroController controller1 = HeroController();
|
||||
|
||||
Reference in New Issue
Block a user