'Generic navigation listener for whole application
I'm trying to find a way to setup a global Navigation listener in the Root of my app (MaterialApp) which can allow me to track all navigation events including the actual route name (/home/page1 for ex.), navigation type etc.
I search something like:
MaterialApp(
initialRoute: '/',
onGenerateRoute: (RouteSettings settings) => route(settings),
onNavigationChange: (RouteType type, String currentRoute) {
// type can an enum be like: 'pop', 'push', 'replace' etc.
// currentRoute is the current route name defined in a pushNamed for example
}
),
Note: this code is non functional, only to illustrate what I want ;)
During my search, I found quite some solutions like RouteObserver, route_observer_mixin which are almost what I'm looking for but I need to wrap all my pages with a mixin... so no a global solution :/
Do you have any clues ?
Thanks in advance,
EDIT thanks to @pskink, see the solution below
Solution 1:[1]
The final solution is to create an extends of the RouteObserver like this:
class MyNavigatorObserver extends RouteObserver<PageRoute<dynamic>> {
@override
void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
super.didPush(route, previousRoute);
if (route is PageRoute) {
// do stuff
}
}
@override
void didReplace({Route<dynamic> newRoute, Route<dynamic> oldRoute}) {
super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
if (newRoute is PageRoute) {
// do stuff
}
}
@override
void didPop(Route<dynamic> route, Route<dynamic> previousRoute) {
super.didPop(route, previousRoute);
if (previousRoute is PageRoute && route is PageRoute) {
// do stuff
}
}
}
and then setup it on the MaterialApp widget:
static MyNavigatorObserver observer =
new MyNavigatorObserver();
MaterialApp(
initialRoute: '/',
onGenerateRoute: (RouteSettings settings) => route(settings),
navigatorObservers: [observer],
),
Thanks @pskink !
Solution 2:[2]
Inspired by @pskink, I've build a generic observer for logging purposes.
Designed to work with navigation 1.0 and unamed routes.
import 'package:flutter/material.dart';
class GlobalNavigatorObserver extends RouteObserver<PageRoute> {
@override
void didPush(route, previousRoute) {
super.didPush(route, previousRoute);
_log('push', previousRoute, route);
}
@override
void didPop(route, previousRoute) {
super.didPop(route, previousRoute);
_log('pop', route, previousRoute);
}
void _log(String method, Route? fromRoute, Route? toRoute) {
debugPrint('[Navigator] ${_getPageName(fromRoute)} => ${_getPageName(toRoute)} ($method)');
}
/// Try to get page name from route.
String _getPageName(dynamic route) {
// Because the builder field is not on a common class, we must try dynamically.
try {
final routeBuilderString = route.builder.toString(); // Example: 'Closure: (BuildContext) => WashingsPage'
return routeBuilderString.substring(routeBuilderString.lastIndexOf(' ') + 1);
} catch(_) {
return 'X';
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | iStornZ |
Solution 2 | Nicolas Youpi |