Routing section of actual combat record of Flutter online project
- 2021-11-13 02:34:16
- OfStack
1. Application scenarios
Often encountered in development
What should I do if I can't get context when the route jumps? eg: token invalidation/remote login jump login page. What should I do if I can't get the current route name? eg: Click push to push and jump to specify the route. If it is already on the current page, replace will be used, and if it is not, push will be used. Register to listen to route jumps, do something you want to do, eg: Different routes, display different status bar colors. Wait...2. Solutions
Solutions:
The routes attribute of MaterialApp assigns the routing array, and the navigatorObservers attribute assigns the routing listener NavigatorManager. didPush/didReplace/didPop/didRemove of NavigatorObserver is implemented in NavigatorManager and recorded in the routing stack List _mRoutes. Jump the route recorded in real time, send a broadcast with stream, and register where you need it.3. Concrete realization
main.dart
MaterialApp(
navigatorObservers: [NavigatorManager.getInstance()],
routes: NavigatorManager.configRoutes,
...
)
navigator_manager.dart
class NavigatorManager extends NavigatorObserver {
/* Configure routes */
static Map<String, WidgetBuilder> configRoutes = {
PackageInfoPage.sName: (context) =>
SplashPage.sName: (context) => SplashPage(),
LoginPage.sName: (context) => SplashPage()),
MainPage.sName: (context) => SplashPage(),
//...
}
// Current routing stack
static List<Route> _mRoutes;
List<Route> get routes => _mRoutes;
// Current route
Route get currentRoute => _mRoutes[_mRoutes.length - 1];
// stream Correlation
static StreamController _streamController;
StreamController get streamController=> _streamController;
// Used to route jumps
static NavigatorState navigator;
/* Single example gives NavigatorManager */
static NavigatorManager navigatorManager;
static NavigatorManager getInstance() {
if (navigatorManager == null) {
navigatorManager = new NavigatorManager();
_streamController = StreamController.broadcast();
}
return navigatorManager;
}
// replace Page
pushReplacementNamed(String routeName, [WidgetBuilder builder]) {
return navigator.pushReplacement(
CupertinoPageRoute(
builder: builder ?? configRoutes[routeName],
settings: RouteSettings(name: routeName),
),
);
}
// push Page
pushNamed(String routeName, [WidgetBuilder builder]) {
return navigator.push(
CupertinoPageRoute(
builder: builder ?? configRoutes[routeName],
settings: RouteSettings(name: routeName),
),
);
}
// pop Page
pop<T extends Object>([T result]) {
navigator.pop(result);
}
// push1 Pages, Remove all pages below this page
pushNamedAndRemoveUntil(String newRouteName) {
return navigator.pushNamedAndRemoveUntil(newRouteName, (Route<dynamic> route) => false);
}
// When the call Navigator.push Time callback
@override
void didPush(Route route, Route previousRoute) {
super.didPush(route, previousRoute);
if (_mRoutes == null) {
_mRoutes = new List<Route>();
}
// Filter the tune here push Is dialog The situation of
if (route is CupertinoPageRoute || route is MaterialPageRoute) {
_mRoutes.add(route);
routeObserver();
}
}
// When the call Navigator.replace Time callback
@override
void didReplace({Route newRoute, Route oldRoute}) {
super.didReplace();
if (newRoute is CupertinoPageRoute || newRoute is MaterialPageRoute) {
_mRoutes.remove(oldRoute);
_mRoutes.add(newRoute);
routeObserver();
}
}
// When the call Navigator.pop Time callback
@override
void didPop(Route route, Route previousRoute) {
super.didPop(route, previousRoute);
if (route is CupertinoPageRoute || route is MaterialPageRoute) {
_mRoutes.remove(route);
routeObserver();
}
}
@override
void didRemove(Route removedRoute, Route oldRoute) {
super.didRemove(removedRoute, oldRoute);
if (removedRoute is CupertinoPageRoute || removedRoute is MaterialPageRoute) {
_mRoutes.remove(removedRoute);
routeObserver();
}
}
void routeObserver() {
LogUtil.i(sName, '&& Routing stack &&');
LogUtil.i(sName, _mRoutes);
LogUtil.i(sName, '&& Current route &&');
LogUtil.i(sName, _mRoutes[_mRoutes.length - 1]);
// Of the current page navigator Which is used to route jumps
navigator = _mRoutes[_mRoutes.length - 1].navigator;
streamController.sink.add(_mRoutes);
}
}
4. How to use
token failure jump
case 401:
ToastUtil.showRed(' Log-in invalidation , Please log in again ');
UserDao.clearAll();
NavigatorManager.getInstance().pushNamedAndRemoveUntil(LoginPage.sName);
break;
Click push to push the jump
static jumpPage(String pageName, [WidgetBuilder builder]) {
String currentRouteName = NavigatorManager.getInstance().currentRoute.settings.name;
// If you are not logged in, do not jump
if (NavigatorManager.getInstance().routes[0].settings.name != MainPage.sName) {
return;
}
// If it is already the current page, replace
if (currentRouteName == pageName) {
NavigatorManager.getInstance().pushReplacementNamed(pageName, builder);
} else {
NavigatorManager.getInstance().pushNamed(pageName, builder);
}
}
Listen for routes to change status bar color
class StatusBarUtil {
static List<String> lightRouteNameList = [
TaskhallPage.sName,
//...
];
static List darkRoutNameList = [
SplashPage.sName,
LoginPage.sName,
MainPage.sName,
//...
];
static init() {
NavigatorManager.getInstance().streamController.stream.listen((state) {
setupStatusBar(state[state.length - 1]);
})
}
setupStatusBar(Route currentRoute) {
if (lightRouteNameList.contains(currentRoute.settings.name)) {
setLight();
} else if (darkRoutNameList.contains(currentRoute.settings.name)) {
setDart();
}
}
}
End, sprinkle flowers in