【问题标题】:Flutter - How the NavigatorObserver class works?Flutter - NavigatorObserver 类如何工作?
【发布时间】:2017-09-11 23:32:08
【问题描述】:

我试图检测 navigator 何时执行基本操作(pushpop),我发现要实现的类这是NavigatorObserver 类,但我找不到关于它如何工作的示例。

我已经尝试过实现接口:

class MyClassState extends State<MyClass> with NavigatorObserver{

    ....

    @override
    void didPop(Route<dynamic> route, Route<dynamic> previousRoute) {
        print('This is never get called');
    }

    @override
    void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
        print('This is never get called');
    }
}

我当然会打电话给Navigator.of(context).push(...); 但是覆盖方法永远不会被调用。

我怀疑与导航器的绑定丢失,但我不确定。

有什么建议吗?

提前致谢!

编辑:

我想我想做的事情很简单,但我不知道该怎么做。

我有一个 page A 推送 page B

页面 B我有一个 定期计时器必须在那里(在 页面 B)。

我要做的就是在 页面 B 弹出(Android 上的后退按钮或应用程序栏中的后退按钮)时使用 timer.cancel() 取消计时器,因为当 page B 弹出,即使 page B 已经消失,计时器仍在执行。

  • 我无法使用 Navigator.pop() 将计时器作为参数传递,因为我不处理后退按钮(应用栏中的后退按钮和 Android 后退按钮)。

编辑 2:

-我找到了解决问题的方法,我所做的就是取消计时器上的

@override
void dispose() {
  timer.cancel();
  super.dispose();
}

方法。但我不确定这是否是实现它的最佳方式。

注意:

使用此解决方法,如果我按下 Home 按钮或在 Android 上打开多任务,计时器仍会执行,当返回应用程序时,它会重新启动,但计时器仍会再次执行其代码。

【问题讨论】:

    标签: dart flutter


    【解决方案1】:

    大多数时候你不需要实现NavigatorObserver。请参阅 this other StackOverflow answer 解释如何使用 pushpop 在路由之间传递信息。在您描述的用例中,您应该将addListener 转换为AnimationController,使用TickerProviderStateMixin 来获取合适的vsync 对象。这可确保在应用程序暂停或您的 State 被释放后不会触发您的回调。 (您可以使用AnimatedBuilderAnimatedWidget 而不是addListener,回调的主要目的是重建小部件树的一部分。)

    您需要NavigatorObserver 的主要时间是使用 Firebase Analytics 之类的插件。您可以在plugins repo 中查看示例用法。您将 navigatorObservers 参数中的 NavigatorObserver 传递给 MaterialApp 构造函数:

    static FirebaseAnalyticsObserver observer =
      new FirebaseAnalyticsObserver(analytics: analytics);
    ...
    return new MaterialApp(
      navigatorObservers: <NavigatorObserver>[observer],
      ...
    );
    

    拥有实现NavigatorObserverState 是不常见的,因为您的MaterialApp 应该靠近小部件层次结构的顶部。在您构建它时,大多数State 对象还不存在,因此您很难将它们放入navigatorObservers 数组中。您可以改为使用不是State 的类。如有必要,您可以使用GlobalKey&lt;MyClassState&gt; 找到需要通知的State(但如果您这样做,可能会有更简单的方法来完成您想要的操作)。

    【讨论】:

    • 哦,非常感谢。我已经用我要解决的主要问题编辑了问题,请检查它,我不知道我是否使用更简单的方法来完成它。
    • 啊哈,您正在尝试解决一个绝对不需要NavigatorObserver 的问题。我编辑了我的答案,提供了一些关于使用 AnimationController 而不是触发计时器的建议。
    • 好的,我明白了,使用 AnimationController 应该可以完美工作,但是,有没有办法定期执行 AnimationController 的回调?正如 Timer.perdiodic 所做的那样?
    • 你可以在AnimationController上调用repeat()让它自动重启,或者你可以在它完成后在AnimationController上调用forward(from: 0.0)
    • 使用AnimationControllerforward(from: 0.0) 解决了这个问题。非常感谢!
    【解决方案2】:
    // Register the RouteObserver as a navigation observer.
    final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();
    void main() {
      runApp(MaterialApp(
        home: Container(),
        navigatorObservers: [routeObserver],
      ));
    }
    
    class RouteAwareWidget extends StatefulWidget {
      State<RouteAwareWidget> createState() => RouteAwareWidgetState();
    }
    
    // Implement RouteAware in a widget's state and subscribe it to the RouteObserver.
    class RouteAwareWidgetState extends State<RouteAwareWidget> with RouteAware {
    
      @override
      void didChangeDependencies() {
        super.didChangeDependencies();
        routeObserver.subscribe(this, ModalRoute.of(context));
      }
    
      @override
      void dispose() {
        routeObserver.unsubscribe(this);
        super.dispose();
      }
    
      @override
      void didPush() {
        // Route was pushed onto navigator and is now topmost route.
      }
    
      @override
      void didPopNext() {
        // Covering route was popped off the navigator.
      }
    
      @override
      Widget build(BuildContext context) => Container();
    
    }
    

    这是一个更详细的帮助指南。 https://medium.com/flutter-community/how-to-track-screen-transitions-in-flutter-with-routeobserver-733984a90dea

    【讨论】:

    • 对 OP 解释为什么这是一个很好的替代已经提供和接受的答案可能会更有帮助。这对你来说可能很明显,但对其他读者来说并不明显。
    • 您会将此代码放在您想观看的每个页面上吗?如果是这样,如果我想查看我的应用程序中的所有页面以在更改时运行功能怎么办
    • @Ares?我也想知道这个。
    • 这是来自 Flutter documentation 的简单复制粘贴。解释在哪里?
    • 所有这些示例都将所有代码显示在一个“文件”中,您将如何从另一个文件中声明的屏幕访问 routeObserver。
    猜你喜欢
    • 2020-04-25
    • 1970-01-01
    • 2020-12-12
    • 2020-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-20
    相关资源
    最近更新 更多