如何使用NavigatorObserver更新ChangeNotifier

时间:2019-09-06 12:28:57

标签: flutter

我想在导航器更改路线时更新一个ChangeNotifier。

我创建了以下NavigatorObserver:

class NotifierNavigatorObserver extends NavigatorObserver {

  NotifierNavigatorObserver(this._changeNotifier);

  MyChangeNotifier _changeNotifier;

  @override
  void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
    _changeNotifier.setFirst(route.isFirst);
  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic> previousRoute) {
    _changeNotifier.setFirst(previousRoute.isFirst);
  }
}

我这样将观察者附加到导航器上:

  @override
  Widget build(BuildContext context) {
    super.build(context);

    final NotifierNavigatorObserver navigatorObserver =
      NotifierNavigatorObserver(Provider.of<MyChangeNotifier>(context, listen: false));

    return Navigator(
        initialRoute: '/',
        onGenerateRoute: _routeFactory,
        onUnknownRoute: _getUnknownRoute,
        observers: [navigatorObserver]
    );
  }

当我运行应用程序时,它运行良好。但是,我确实在日志中收到以下错误:

I/flutter ( 9191): ══╡ EXCEPTION CAUGHT BY FOUNDATION LIBRARY ╞════════════════════════════════════════════════════════
I/flutter ( 9191): The following assertion was thrown while dispatching notifications for MyChangeNotifier:
I/flutter ( 9191): setState() or markNeedsBuild() called during build.
I/flutter ( 9191): This ChangeNotifierProvider<MyChangeNotifier> widget cannot be marked as needing to build because the
I/flutter ( 9191): framework is already in the process of building widgets.  A widget can be marked as needing to be
I/flutter ( 9191): built during the build phase only if one of its ancestors is currently building. This exception is
I/flutter ( 9191): allowed because the framework builds parent widgets before children, which means a dirty descendant
I/flutter ( 9191): will always be built. Otherwise, the framework might not visit this widget during this build phase.
I/flutter ( 9191): The widget on which setState() or markNeedsBuild() was called was:
I/flutter ( 9191):   ChangeNotifierProvider<MyChangeNotifier>
I/flutter ( 9191): The widget which was currently being built when the offending call was made was:
I/flutter ( 9191):   HomeRoot

我该怎么办才能消除此错误消息?

1 个答案:

答案 0 :(得分:1)

在窗口小部件树仍在构建时,会调用

didPush / didPop事件。

为防止这些异常,请将您的突变包装到Future.microtask中:

  @override
  void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
    Future.microstask(() {
      _changeNotifier.setFirst(route.isFirst);
    });
  }