flutter 应用场景_Flutter上线项目实战记录之路由篇

本文详细介绍了在Flutter开发中遇到的路由跳转问题,如无context、获取当前路由名等,并提出解决方案。通过自定义NavigatorObserver类NavigatorManager,配置路由数组并监听路由变化,实现实时广播路由状态。同时,展示了如何使用该管理器进行页面跳转、监听路由改变以调整状态栏颜色,提供了一种实用的路由管理方式。
摘要由CSDN通过智能技术生成

1. 应用场景

开发中经常遇到

路由跳转时拿不到context怎么办,eg: token失效/异地登录跳转登录页面。

获取不到当前路由名称怎么办,eg: 点击push推送跳转指定路由,如果已经在当前页面就replace,如果不在就push。

注册监听路由跳转,做一些想做的事情 ,eg:不同路由,显示不同状态栏颜色。

等等...

2. 解决方案

解决思路:

MaterialApp 的routes属性赋值路由数组,navigatorObservers属性赋值路由监听对象NavigatorManager。

在NavigatorManager里实现NavigatorObserver的didPush/didReplace/didPop/didRemove,并记录到路由栈List _mRoutes中。

将实时记录的路由跳转,用stream发一个广播,哪里需要哪里注册。

3. 具体实现

main.dart

MaterialApp(

navigatorObservers: [NavigatorManager.getInstance()],routes: NavigatorManager.configRoutes,...

)

navigator_manager.dart

class NavigatorManager extends NavigatorObserver {

/* 配置routes */

static Map configRoutes = {

PackageInfoPage.sName: (context) =>

SplashPage.sName: (context) => SplashPage(),LoginPage.sName: (context) => SplashPage()),MainPage.sName: (context) => SplashPage(),//...

}

// 当前路由栈

static List _mRoutes;

List get routes => _mRoutes;

// 当前路由

Route get currentRoute => _mRoutes[_mRoutes.length - 1];

// stream相关

static StreamController _streamController;

StreamController get streamController=> _streamController;

// 用来路由跳转

static NavigatorState navigator;

/* 单例给出NavigatorManager */

static NavigatorManager navigatorManager;

static NavigatorManager getInstance() {

if (navigatorManager == null) {

navigatorManager = new NavigatorManager();

_streamController = StreamController.broadcast();

}

return navigatorManager;

}

// replace 页面

pushReplacementNamed(String routeName,[WidgetBuilder builder]) {

return navigator.pushReplacement(

CupertinoPageRoute(

builder: builder ?? configRoutes[routeName],settings: RouteSettings(name: routeName),),);

}

// push 页面

pushNamed(String routeName,[WidgetBuilder builder]) {

return navigator.push(

CupertinoPageRoute(

builder: builder ?? configRoutes[routeName],);

}

// pop 页面

pop([T result]) {

navigator.pop(result);

}

// push一个页面, 移除该页面下面所有页面

pushNamedAndRemoveUntil(String newRouteName) {

return navigator.pushNamedAndRemoveUntil(newRouteName,(Route route) => false);

}

// 当调用Navigator.push时回调

@override

void didPush(Route route,Route previousRoute) {

super.didPush(route,previousRoute);

if (_mRoutes == null) {

_mRoutes = new List();

}

// 这里过滤调push的是dialog的情况

if (route is CupertinoPageRoute || route is MaterialPageRoute) {

_mRoutes.add(route);

routeObserver();

}

}

// 当调用Navigator.replace时回调

@override

void didReplace({Route newRoute,Route oldRoute}) {

super.didReplace();

if (newRoute is CupertinoPageRoute || newRoute is MaterialPageRoute) {

_mRoutes.remove(oldRoute);

_mRoutes.add(newRoute);

routeObserver();

}

}

// 当调用Navigator.pop时回调

@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,'&&路由栈&&');

LogUtil.i(sName,_mRoutes);

LogUtil.i(sName,'&&当前路由&&');

LogUtil.i(sName,_mRoutes[_mRoutes.length - 1]);

// 当前页面的navigator,用来路由跳转

navigator = _mRoutes[_mRoutes.length - 1].navigator;

streamController.sink.add(_mRoutes);

}

}

4. 如何使用

token失效跳转

case 401:

ToastUtil.showRed('登录失效,请重新登陆');

UserDao.clearAll();

NavigatorManager.getInstance().pushNamedAndRemoveUntil(LoginPage.sName);

break;

点击push推送跳转

static jumpPage(String pageName,[WidgetBuilder builder]) {

String currentRouteName = NavigatorManager.getInstance().currentRoute.settings.name;

// 如果是未登录,不跳转

if (NavigatorManager.getInstance().routes[0].settings.name != MainPage.sName) {

return;

}

// 如果已经是当前页面就replace

if (currentRouteName == pageName) {

NavigatorManager.getInstance().pushReplacementNamed(pageName,builder);

} else {

NavigatorManager.getInstance().pushNamed(pageName,builder);

}

}

监听路由改变状态栏颜色

class StatusBarUtil {

static List 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();

}

}

}

完结,撒花🎉

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值