Avoid retaining routes when subscriptions are cleared (#88310)
This commit is contained in:
parent
ddb8bfb72b
commit
a4f5a5871a
@ -1733,6 +1733,19 @@ abstract class PopupRoute<T> extends ModalRoute<T> {
|
|||||||
class RouteObserver<R extends Route<dynamic>> extends NavigatorObserver {
|
class RouteObserver<R extends Route<dynamic>> extends NavigatorObserver {
|
||||||
final Map<R, Set<RouteAware>> _listeners = <R, Set<RouteAware>>{};
|
final Map<R, Set<RouteAware>> _listeners = <R, Set<RouteAware>>{};
|
||||||
|
|
||||||
|
/// Whether this observer is managing changes for the specified route.
|
||||||
|
///
|
||||||
|
/// If asserts are disabled, this method will throw an exception.
|
||||||
|
@visibleForTesting
|
||||||
|
bool debugObservingRoute(R route) {
|
||||||
|
late bool contained;
|
||||||
|
assert(() {
|
||||||
|
contained = _listeners.containsKey(route);
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
|
return contained;
|
||||||
|
}
|
||||||
|
|
||||||
/// Subscribe [routeAware] to be informed about changes to [route].
|
/// Subscribe [routeAware] to be informed about changes to [route].
|
||||||
///
|
///
|
||||||
/// Going forward, [routeAware] will be informed about qualifying changes
|
/// Going forward, [routeAware] will be informed about qualifying changes
|
||||||
@ -1753,9 +1766,15 @@ class RouteObserver<R extends Route<dynamic>> extends NavigatorObserver {
|
|||||||
/// subscribed to multiple types, this will unregister it (once) from each type.
|
/// subscribed to multiple types, this will unregister it (once) from each type.
|
||||||
void unsubscribe(RouteAware routeAware) {
|
void unsubscribe(RouteAware routeAware) {
|
||||||
assert(routeAware != null);
|
assert(routeAware != null);
|
||||||
for (final R route in _listeners.keys) {
|
final List<R> routes = _listeners.keys.toList();
|
||||||
|
for (final R route in routes) {
|
||||||
final Set<RouteAware>? subscribers = _listeners[route];
|
final Set<RouteAware>? subscribers = _listeners[route];
|
||||||
subscribers?.remove(routeAware);
|
if (subscribers != null) {
|
||||||
|
subscribers.remove(routeAware);
|
||||||
|
if (subscribers.isEmpty) {
|
||||||
|
_listeners.remove(route);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,6 +525,33 @@ void main() {
|
|||||||
expect(pageRouteAware.didPushCount, 2);
|
expect(pageRouteAware.didPushCount, 2);
|
||||||
expect(pageRouteAware.didPopCount, 0);
|
expect(pageRouteAware.didPopCount, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('releases reference to route when unsubscribed', () {
|
||||||
|
final RouteObserver<PageRoute<dynamic>> observer = RouteObserver<PageRoute<dynamic>>();
|
||||||
|
final MockRouteAware pageRouteAware = MockRouteAware();
|
||||||
|
final MockRouteAware page2RouteAware = MockRouteAware();
|
||||||
|
final MockPageRoute pageRoute = MockPageRoute();
|
||||||
|
final MockPageRoute nextPageRoute = MockPageRoute();
|
||||||
|
observer.subscribe(pageRouteAware, pageRoute);
|
||||||
|
observer.subscribe(pageRouteAware, nextPageRoute);
|
||||||
|
observer.subscribe(page2RouteAware, pageRoute);
|
||||||
|
observer.subscribe(page2RouteAware, nextPageRoute);
|
||||||
|
expect(pageRouteAware.didPushCount, 2);
|
||||||
|
expect(page2RouteAware.didPushCount, 2);
|
||||||
|
|
||||||
|
expect(observer.debugObservingRoute(pageRoute), true);
|
||||||
|
expect(observer.debugObservingRoute(nextPageRoute), true);
|
||||||
|
|
||||||
|
observer.unsubscribe(pageRouteAware);
|
||||||
|
|
||||||
|
expect(observer.debugObservingRoute(pageRoute), true);
|
||||||
|
expect(observer.debugObservingRoute(nextPageRoute), true);
|
||||||
|
|
||||||
|
observer.unsubscribe(page2RouteAware);
|
||||||
|
|
||||||
|
expect(observer.debugObservingRoute(pageRoute), false);
|
||||||
|
expect(observer.debugObservingRoute(nextPageRoute), false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Can autofocus a TextField nested in a Focus in a route.', (WidgetTester tester) async {
|
testWidgets('Can autofocus a TextField nested in a Focus in a route.', (WidgetTester tester) async {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user