23

Is there a way to listen to route changes of the Navigator in Flutter? Basically, I'd like to be notified when a route is pushed or popped, and have the current route on display on screen be returned from the notification

user3217522
  • 5,786
  • 7
  • 26
  • 34

4 Answers4

10

Building on navigator observers, you can also use RouteObserver and RouteAware.

Thibault
  • 375
  • 2
  • 4
  • 15
6

Navigator has observers. You can implement NavigatorObserver and receive notifications with details.

Mahesh Jamdade
  • 17,235
  • 8
  • 110
  • 131
German Saprykin
  • 6,631
  • 2
  • 29
  • 26
3

I was also struggling with that and for my purpose the RouteObservers felt overkill and were too much for my needs. The way I handled it lately was to use the onGenerateRoute property inside my MaterialApp. So this solution is more applicable if you are using onGenerateRoute with your app (might especially be useful if you are navigating with arguments). You can read more about it here.

My MaterialApp looks like the following:

runApp(MaterialApp(
        title: 'bla',
        home: BuilderPage(LoginArguments(false)),
        onGenerateRoute: generateRoute
));

The generateRoute method looks like the following:

Route<dynamic> generateRoute(RouteSettings settings) {
  switch (settings.name) {
    case 'main':
      print('Navigated to main')
      return MaterialPageRoute(builder: (_) => MainScreen());
    case 'register':
      print('Navigated to register')
      return MaterialPageRoute(builder: (_) => RegisterScreen());
    default:
      return MaterialPageRoute(
          builder: (_) => Scaffold(
                body: Center(
                    child: Text('No route defined for ${settings.name}')),
              ));
  }
}

So everytime I now do for example:

Navigator.pushNamed(
        context,
        'register',
      );

It will print Navigated to register. I think this way is especially helpful if you don't necessarily need to know whether you pushed or popped. With some additional implementation it would also be possible to observe that via injected arguments.

LOLWTFasdasd asdad
  • 2,625
  • 5
  • 26
  • 39
0
  1. Using auto_router
class LoggingNavigationObserver extends AutoRouterObserver {
  @override
  void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
    super.didPush(route, previousRoute);
    print('Current Screen push: ${route.settings.name}');

  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
    super.didPop(route, previousRoute);
    //print('Current Screen pop: ${route.settings.name}');
    
  }

  @override
  void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute}) {
    super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
    print('Current Screen replace: ${newRoute?.settings.name}');
   
  }

  @override
  void didRemove(Route<dynamic> route, Route<dynamic>? previousRoute) {
    super.didRemove(route, previousRoute);
    print('Current Screen remove: ${route.settings.name}');
  
  }

  @override
  void didChangeTabRoute(TabPageRoute route, TabPageRoute? previousRoute) {
    // Handle tab route change in the navigator
    print('Tab route changed: ${route.name}');
   
  }

 
}

default flutter router source

class MyRouteObserver extends RouteObserver<PageRoute<dynamic>> {
  void _sendScreenView(PageRoute<dynamic> route) {
    var screenName = route.settings.name;
    print('screenName $screenName');
    // do something with it, ie. send it to your analytics service collector
  }

  @override
  void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
    super.didPush(route, previousRoute);
    if (route is PageRoute) {
      _sendScreenView(route);
    }
  }

  @override
  void didReplace({Route<dynamic> newRoute, Route<dynamic> oldRoute}) {
    super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
    if (newRoute is PageRoute) {
      _sendScreenView(newRoute);
    }
  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic> previousRoute) {
    super.didPop(route, previousRoute);
    if (previousRoute is PageRoute && route is PageRoute) {
      _sendScreenView(previousRoute);
    }
  }
}

Register your observers as usual and you should be good to go.

griffins
  • 7,079
  • 4
  • 29
  • 54