Flutter上线项目实战记录之路由篇

 更新时间:2019年09月06日 14:20:12   作者:callme大帅  
这篇文章主要给大家介绍了关于Flutter上线项目实战记录之路由篇的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Flutter具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

1. 应用场景

开发中经常遇到

  • 路由跳转时拿不到context怎么办,eg: token失效/异地登录跳转登录页面。
  • 获取不到当前路由名称怎么办,eg: 点击push推送跳转指定路由,如果已经在当前页面就replace,如果不在就push。
  • 注册监听路由跳转,做一些想做的事情 ,eg:不同路由,显示不同状态栏颜色。
  • 等等...

2. 解决方案

解决思路:

  1. MaterialApp 的routes属性赋值路由数组,navigatorObservers属性赋值路由监听对象NavigatorManager。
  2. 在NavigatorManager里实现NavigatorObserver的didPush/didReplace/didPop/didRemove,并记录到路由栈List _mRoutes中。
  3. 将实时记录的路由跳转,用stream发一个广播,哪里需要哪里注册。

3. 具体实现

main.dart

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

navigator_manager.dart

class NavigatorManager extends NavigatorObserver {
 /* 配置routes */
 static Map<String, WidgetBuilder> configRoutes = {
 PackageInfoPage.sName: (context) =>
 SplashPage.sName: (context) => SplashPage(),
 LoginPage.sName: (context) => SplashPage()),
 MainPage.sName: (context) => SplashPage(),
 //...
 }
 // 当前路由栈
 static List<Route> _mRoutes;
 List<Route> 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],
  settings: RouteSettings(name: routeName),
  ),
 );
 }
 
 // pop 页面
 pop<T extends Object>([T result]) {
 navigator.pop(result);
 }
 
 // push一个页面, 移除该页面下面所有页面
 pushNamedAndRemoveUntil(String newRouteName) {
 return navigator.pushNamedAndRemoveUntil(newRouteName, (Route<dynamic> route) => false);
 }
 
 // 当调用Navigator.push时回调
 @override
 void didPush(Route route, Route previousRoute) {
 super.didPush(route, previousRoute);
 if (_mRoutes == null) {
  _mRoutes = new List<Route>();
 }
 // 这里过滤调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<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();
    }
   }
}

完结,撒花🎉

总结

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

相关文章

  • Android动画学习笔记之补间动画

    Android动画学习笔记之补间动画

    这篇文章主要为大家详细介绍了Android动画学习笔记之补间动画,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • Android studio 运行main 函数的方法

    Android studio 运行main 函数的方法

    这篇文章主要介绍了Android studio 运行main 函数的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • Flutter实现一个支持渐变背景的Button示例详解

    Flutter实现一个支持渐变背景的Button示例详解

    这篇文章主要为大家介绍了Flutter实现一个支持渐变背景的Button示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • Android编程之菜单实现方法

    Android编程之菜单实现方法

    这篇文章主要介绍了Android编程之菜单实现方法,以实例形式较为详细的分析了Android编程实现菜单的布局及功能相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-11-11
  • Android利用Dom对XML进行增删改查操作详解

    Android利用Dom对XML进行增删改查操作详解

    使用DOM进行增删改查,这个是DOM的优势所在,其实代码很简单,不需要过多的解释,下面这篇文章主要给大家介绍了关于Android利用Dom对XML进行增删改查操作的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下。
    2018-01-01
  • Android开发Launcher进程启动流程

    Android开发Launcher进程启动流程

    这篇文章主要为大家介绍了Android开发Launcher进程启动流程示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • Android实现系统重新启动的功能

    Android实现系统重新启动的功能

    有些Android版本没有系统重启的功能,非常不方便。需要我们自己开发一个能够重新启动的应用
    2013-11-11
  • Android Http协议访问网络实例(3种)

    Android Http协议访问网络实例(3种)

    本篇文章主要介绍了Android Http协议访问网络实例(3种),具有一定的参考价值,有兴趣的可以了解一下
    2017-07-07
  • Android自定义View新年烟花、祝福语横幅动画

    Android自定义View新年烟花、祝福语横幅动画

    这篇文章主要为大家详细介绍了Android自定义View新年烟花、祝福语横幅动画,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • Android实现日期时间选择对话框

    Android实现日期时间选择对话框

    这篇文章主要为大家详细介绍了Android实现日期以及时间选择对话框,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09

最新评论