HeroController should dispatch creation and disposal events. (#137835)
This commit is contained in:
parent
0e7ed92988
commit
e8d9d9bfd5
@ -156,6 +156,12 @@ class _CupertinoTabViewState extends State<CupertinoTabView> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_heroController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
void _updateObservers() {
|
void _updateObservers() {
|
||||||
_navigatorObservers =
|
_navigatorObservers =
|
||||||
List<NavigatorObserver>.of(widget.navigatorObservers)
|
List<NavigatorObserver>.of(widget.navigatorObservers)
|
||||||
|
@ -784,7 +784,17 @@ class HeroController extends NavigatorObserver {
|
|||||||
///
|
///
|
||||||
/// The [createRectTween] argument is optional. If null, the controller uses a
|
/// The [createRectTween] argument is optional. If null, the controller uses a
|
||||||
/// linear [Tween<Rect>].
|
/// linear [Tween<Rect>].
|
||||||
HeroController({ this.createRectTween });
|
HeroController({ this.createRectTween }) {
|
||||||
|
// TODO(polina-c): stop duplicating code across disposables
|
||||||
|
// https://github.com/flutter/flutter/issues/137435
|
||||||
|
if (kFlutterMemoryAllocationsEnabled) {
|
||||||
|
MemoryAllocations.instance.dispatchObjectCreated(
|
||||||
|
library: 'package:flutter/widgets.dart',
|
||||||
|
className: '$HeroController',
|
||||||
|
object: this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Used to create [RectTween]s that interpolate the position of heroes in flight.
|
/// Used to create [RectTween]s that interpolate the position of heroes in flight.
|
||||||
///
|
///
|
||||||
@ -1043,6 +1053,12 @@ class HeroController extends NavigatorObserver {
|
|||||||
/// Releases resources.
|
/// Releases resources.
|
||||||
@mustCallSuper
|
@mustCallSuper
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
// TODO(polina-c): stop duplicating code across disposables
|
||||||
|
// https://github.com/flutter/flutter/issues/137435
|
||||||
|
if (kFlutterMemoryAllocationsEnabled) {
|
||||||
|
MemoryAllocations.instance.dispatchObjectDisposed(object: this);
|
||||||
|
}
|
||||||
|
|
||||||
for (final _HeroFlight flight in _flights.values) {
|
for (final _HeroFlight flight in _flights.values) {
|
||||||
flight.dispose();
|
flight.dispose();
|
||||||
}
|
}
|
||||||
|
@ -1060,6 +1060,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgetsWithLeakTracking('MaterialApp does create HeroController with the MaterialRectArcTween', (WidgetTester tester) async {
|
testWidgetsWithLeakTracking('MaterialApp does create HeroController with the MaterialRectArcTween', (WidgetTester tester) async {
|
||||||
final HeroController controller = MaterialApp.createMaterialHeroController();
|
final HeroController controller = MaterialApp.createMaterialHeroController();
|
||||||
|
addTearDown(controller.dispose);
|
||||||
final Tween<Rect?> tween = controller.createRectTween!(
|
final Tween<Rect?> tween = controller.createRectTween!(
|
||||||
const Rect.fromLTRB(0.0, 0.0, 10.0, 10.0),
|
const Rect.fromLTRB(0.0, 0.0, 10.0, 10.0),
|
||||||
const Rect.fromLTRB(0.0, 0.0, 20.0, 20.0),
|
const Rect.fromLTRB(0.0, 0.0, 20.0, 20.0),
|
||||||
|
@ -304,9 +304,12 @@ Future<void> main() async {
|
|||||||
testWidgetsWithLeakTracking('Heroes still animate after hero controller is swapped.', (WidgetTester tester) async {
|
testWidgetsWithLeakTracking('Heroes still animate after hero controller is swapped.', (WidgetTester tester) async {
|
||||||
final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
|
final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
|
||||||
final UniqueKey heroKey = UniqueKey();
|
final UniqueKey heroKey = UniqueKey();
|
||||||
|
final HeroController controller1 = HeroController();
|
||||||
|
addTearDown(controller1.dispose);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
HeroControllerScope(
|
HeroControllerScope(
|
||||||
controller: HeroController(),
|
controller: controller1,
|
||||||
child: TestDependencies(
|
child: TestDependencies(
|
||||||
child: Navigator(
|
child: Navigator(
|
||||||
key: key,
|
key: key,
|
||||||
@ -352,15 +355,19 @@ Future<void> main() async {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
expect(find.byKey(heroKey), findsNothing);
|
expect(find.byKey(heroKey), findsNothing);
|
||||||
// Begins the navigation
|
// Begins the navigation
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
await tester.pump(const Duration(milliseconds: 30));
|
await tester.pump(const Duration(milliseconds: 30));
|
||||||
expect(find.byKey(heroKey), isOnstage);
|
expect(find.byKey(heroKey), isOnstage);
|
||||||
|
final HeroController controller2 = HeroController();
|
||||||
|
addTearDown(controller2.dispose);
|
||||||
|
|
||||||
// Pumps a new hero controller.
|
// Pumps a new hero controller.
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
HeroControllerScope(
|
HeroControllerScope(
|
||||||
controller: HeroController(),
|
controller: controller2,
|
||||||
child: TestDependencies(
|
child: TestDependencies(
|
||||||
child: Navigator(
|
child: Navigator(
|
||||||
key: key,
|
key: key,
|
||||||
@ -389,6 +396,7 @@ Future<void> main() async {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// The original animation still flies.
|
// The original animation still flies.
|
||||||
expect(find.byKey(heroKey), isOnstage);
|
expect(find.byKey(heroKey), isOnstage);
|
||||||
// Waits for the animation finishes.
|
// Waits for the animation finishes.
|
||||||
@ -3135,6 +3143,13 @@ Future<void> main() async {
|
|||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(tester.getTopLeft(find.byType(Image)).dy, moreOrLessEquals(forwardRest, epsilon: 0.1));
|
expect(tester.getTopLeft(find.byType(Image)).dy, moreOrLessEquals(forwardRest, epsilon: 0.1));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('HeroController dispatches memory events', () async {
|
||||||
|
await expectLater(
|
||||||
|
await memoryEvents(() => HeroController().dispose(), HeroController),
|
||||||
|
areCreateAndDispose,
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestDependencies extends StatelessWidget {
|
class TestDependencies extends StatelessWidget {
|
||||||
|
@ -2367,6 +2367,8 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
addTearDown(spy.dispose);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
HeroControllerScope(
|
HeroControllerScope(
|
||||||
controller: spy,
|
controller: spy,
|
||||||
@ -2437,6 +2439,8 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
addTearDown(spy.dispose);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
HeroControllerScope(
|
HeroControllerScope(
|
||||||
controller: spy,
|
controller: spy,
|
||||||
@ -2506,6 +2510,7 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
addTearDown(spy1.dispose);
|
||||||
final List<NavigatorObservation> observations2 = <NavigatorObservation>[];
|
final List<NavigatorObservation> observations2 = <NavigatorObservation>[];
|
||||||
final HeroControllerSpy spy2 = HeroControllerSpy()
|
final HeroControllerSpy spy2 = HeroControllerSpy()
|
||||||
..onPushed = (Route<dynamic>? route, Route<dynamic>? previousRoute) {
|
..onPushed = (Route<dynamic>? route, Route<dynamic>? previousRoute) {
|
||||||
@ -2517,6 +2522,8 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
addTearDown(spy2.dispose);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
TestDependencies(
|
TestDependencies(
|
||||||
child: Stack(
|
child: Stack(
|
||||||
@ -2633,6 +2640,8 @@ void main() {
|
|||||||
|
|
||||||
testWidgetsWithLeakTracking('hero controller subscribes to multiple navigators does throw', (WidgetTester tester) async {
|
testWidgetsWithLeakTracking('hero controller subscribes to multiple navigators does throw', (WidgetTester tester) async {
|
||||||
final HeroControllerSpy spy = HeroControllerSpy();
|
final HeroControllerSpy spy = HeroControllerSpy();
|
||||||
|
addTearDown(spy.dispose);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
HeroControllerScope(
|
HeroControllerScope(
|
||||||
controller: spy,
|
controller: spy,
|
||||||
@ -2671,6 +2680,8 @@ void main() {
|
|||||||
|
|
||||||
testWidgetsWithLeakTracking('hero controller throws has correct error message', (WidgetTester tester) async {
|
testWidgetsWithLeakTracking('hero controller throws has correct error message', (WidgetTester tester) async {
|
||||||
final HeroControllerSpy spy = HeroControllerSpy();
|
final HeroControllerSpy spy = HeroControllerSpy();
|
||||||
|
addTearDown(spy.dispose);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
HeroControllerScope(
|
HeroControllerScope(
|
||||||
controller: spy,
|
controller: spy,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user