我有一个方法,每次在导航器堆栈中推送/弹出新路由时都需要调用。基本上,每次用户从一个屏幕转到另一个屏幕时。
我读到,执行此操作的最佳方法是使用 NavigatorObserver。 我尝试以这种方式实现它:
class NavigationObserver extends NavigatorObserver {
@override
void didPush(Route route, Route? previousRoute) {
super.didPush(route, previousRoute);
NotificationsViewState().updateNotifs(); // "Notifications" page
NotifScrollContentState().updateNotifs(); // content of the notifications modal
}
}
使用这个类,我在我的主 MaterialApp 中实现了它:
MaterialApp(
navigatorObservers: [NavigationObserver()],
// etc...
这导致了一个错误,暗示 GlobalKeys 可能是其中的原因:
GlobalKey 在一个小部件的子列表中多次使用。
有问题的 GlobalKey 是:[GlobalObjectKey_WidgetsAppState#263c0]
具有该键的小部件的父级是: _FocusInheritedScop
第一个使用该键实例化的孩子变成了: 导航器-[GlobalObjectKey_WidgetsAppState#263c0]
使用该键实例化的第二个子项是: _焦点继承范围
GlobalKey 一次只能在小部件树中的一个小部件上指定。
我不是 Dart 专家,所以我确实很难理解如何解决这个问题。 仅供参考,我在 Flutter 应用程序中使用的唯一 GlobalKeys 仅用于实现 AnimatedLists,所以我认为这不相关。
我也遇到了同样的问题,虽然不知道具体原因, 我能够通过将 didPush、didPop、didReplace 和 didRemove 等函数中的繁重任务移至单独的线程来解决这个问题。
看来在 didPush 函数中运行以下代码可能是原因:
NotificationsViewState().updateNotifs(); // "Notifications" page
NotifScrollContentState().updateNotifs(); // content of the notifications modal
由于我对原因没有准确的了解,所以很难提供明确的解决方案。 但是,将这些任务的执行更改为单独的线程(如下所示)可能有助于解决问题:
导航观察者:
class RouteTrackerInfo {
final Route<dynamic>? route;
final Route<dynamic>? previousRoute;
RouteTrackerInfo({
this.route,
this.previousRoute,
});
}
class NavigationObserver extends NavigatorObserver {
final void Function(RouteTrackerInfo info)? onRouteChanged;
NavigationObserver({
this.onRouteChanged
});
@override
void didPush(Route route, Route? previousRoute) {
super.didPush(route, previousRoute);
onRouteChanged?.call(RouteTrackerInfo(route: route, previousRoute: previousRoute));
}
}
您的小部件状态:
class _MyAppState extends State<MyApp> {
static final BehaviorSubject<RouteTrackerInfo> _routeTrackerInfoStream = BehaviorSubject.seeded(RouteTrackerInfo(route: null, previousRoute: null));
@override
void initState() {
super.initState();
_routeTrackerInfoStream.listen((routeTrackerInfo) {
print('Route changed: ${routeTrackerInfo.route?.settings.name}');
NotificationsViewState().updateNotifs(); // "Notifications" page
NotifScrollContentState().updateNotifs(); // content of the notifications modal
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
...
navigatorObservers: [
NavigationObserver(
onRouteChanged: (info) {
_routeTrackerInfoStream.add(info);
}
),
],
...
);
}
}