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 {
|
||||
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].
|
||||
///
|
||||
/// 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.
|
||||
void unsubscribe(RouteAware routeAware) {
|
||||
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];
|
||||
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.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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user