首页 > 其他分享 >Flutter路由管理

Flutter路由管理

时间:2024-10-18 20:47:17浏览次数:11  
标签:管理 context Navigator 路由表 Flutter 路由 页面

前言

这篇文章我通过页面跳转、路由传参、命名路由、路由生成钩子的顺序从简入深的说明Flutter的路由。

想要了解Flutter的路由就要了解MaterialPageRoute和Navigator

MaterialPageRoute

MaterialPageRoute继承自PageRoute类,PageRoute类是一个抽象类,表示占有整个屏幕空间的一个模态路由页面,它还定义了路由构建及切换时过渡动画的相关接口及属性。MaterialPageRoute 是 Material 组件库提供的组件,它可以针对不同平台,实现与平台页面切换动画风格一致的路由切换动画:

  • 对于 Android,当打开新页面时,新的页面会从屏幕底部滑动到屏幕顶部;当关闭页面时,当前页面会从屏幕顶部滑动到屏幕底部后消失,同时上一个页面会显示到屏幕上。
  • 对于 iOS,当打开页面时,新的页面会从屏幕右侧边缘一致滑动到屏幕左边,直到新页面全部显示到屏幕上,而上一个页面则会从当前屏幕滑动到屏幕左侧而消失;当关闭页面时,正好相反,当前页面会从屏幕右侧滑出,同时上一个页面会从屏幕左侧滑入。
MaterialPageRoute 构造函数的各个参数的意义
MaterialPageRoute({
    WidgetBuilder builder,
    RouteSettings settings,
    bool maintainState = true,
    bool fullscreenDialog = false,
  })

参数

意义

builder是一个 WidgetBuilder 类型的回调函数,它的作用是构建路由页面的具体内容,返回值是一个widget。我们通常要实现此回调,返回新路由的实例。
settings包含路由的配置信息,如路由名称、是否初始路由(首页)。
maintainState默认情况下,当入栈一个新路由时,原来的路由仍然会被保存在内存中,如果想在路由没用的时候释放其所占用的所有资源,可以设置maintainState为false
fullscreenDialog示新的路由页面是否是一个全屏的模态对话框,在 iOS 中,如果fullscreenDialogtrue,新页面将会从屏幕底部滑入(而不是水平方向)。

Navigator

Navigator是一个路由管理的组件,它提供了打开和退出路由页方法。Navigator通过一个栈来管理活动路由集合。通常当前屏幕显示的页面就是栈顶的路由。Navigator提供了一系列方法来管理路由栈,在此我们只介绍其最常用的两个方法:

常用方法
方法描述

Future push(BuildContext context, Route route)

将给定的路由入栈(即打开新的页面),返回值是一个Future对象,用以接收新路由出栈(即关闭)时的返回数据。

bool pop(BuildContext context, [ result ])

将栈顶路由出栈,result为页面关闭时返回给上一个页面的数据。

Navigator 还有很多其它方法,如Navigator.replaceNavigator.popUntil

实例方法

Navigator 类中第一个参数为 context 的静态方法都对应一个 Navigator 的实例方法, 比如Navigator.push(BuildContext context, Route route)等价于Navigator.of(context).push(Route route) ,下面命名路由相关的方法也是一样的

路由管理

页面跳转

通过Navigator.push( context,MaterialPageRoute(builder: (context) {return NewRoute();}));来实现跳转到NewRoute界面

//导包,此行代码作用是导入了 Material UI 组件库。Material (opens new window)是一种标准的移动端和 web 端的视觉设计语言, Flutter默认提供了一套丰富的 Material 风格的 UI 组件。
import 'package:flutter/material.dart';

//应用入口
void main() {
  runApp(const MyApp());
}

/// 在 Flutter 中,大多数东西都是 widget(后同“组件”或“部件”),包括对齐(alignment)、填充(padding)和布局(layout)等,它们都是以 widget 的形式提供。
class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override

  ///Flutter 在构建页面时,会调用组件的build方法,widget 的主要工作是提供一个 build()方法来描述如何构建 UI 界面(通常是通过组合、拼装其它基础 widget)。
  Widget build(BuildContext context) {
    ///MaterialApp 是 Material 库中提供的 Flutter APP 框架,通过它可以设置应用的名称、主题、语言、首页及路由列表等。MaterialApp也是一个 widget。
    return MaterialApp(
      //用于名称
      title: 'Flutter Demo',
      //主题
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      //home 为 Flutter 应用的首页,它也是一个 widget。
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});
  final title = 'home界面';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
          child: Row(
        children: [
          Text(title),
          TextButton(
            style: TextButton.styleFrom(
                backgroundColor: Colors.white,
                textStyle: const TextStyle(color: Colors.white)),
            onPressed: () {
              //导航到新路由

              Navigator.push(context, MaterialPageRoute(builder: (context) {
                return const NewRoute();
              }));
            },
            child: const Text("跳转到测试界面"),
          ),
        ],
      )),
    );
  }
}

class NewRoute extends StatelessWidget {
  const NewRoute({super.key});

  final title = '路由测试';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
          child: Row(
        children: [
          Text(title),
          TextButton(
            style: TextButton.styleFrom(
                backgroundColor: Colors.white,
                textStyle: const TextStyle(color: Colors.white)),
            onPressed: () {
              //导航到新路由

              Navigator.push(context, MaterialPageRoute(builder: (context) {
                return const MyApp();
              }));
            },
            child: const Text("跳转回去"),
          ),
        ],
      )),
    );
  }
}

我们只要点击按钮就可以进行跳转了

命名路由

所谓“命名路由”(Named Route)即有名字的路由,我们可以先给路由起一个名字,然后就可以通过路由名字直接打开新的路由了,这为路由管理带来了一种直观、简单的方式。

路由表

要想使用命名路由,我们必须先提供并注册一个路由表(routing table),这样应用程序才知道哪个名字与哪个路由组件相对应。其实注册路由表就是给路由起名字,路由表的定义如下:

Map<String, WidgetBuilder> routes;

它是一个Map,key 为路由的名字,是个字符串;value 是个builder回调函数,用于生成相应的路由 widget。我们在通过路由名字打开新路由时,应用会根据路由名字在路由表中查找到对应的WidgetBuilder回调函数,然后调用该回调函数生成路由 widget 并返回。

注册路由表

路由表的注册方式很简单,我们在MyApp类的build方法中找到MaterialApp,添加routes属性,代码如下:

MaterialApp(
  title: 'Flutter Demo',
  theme: ThemeData(
    primarySwatch: Colors.blue,
  ),
  //注册路由表
  routes:{
   "new_page":(context) => NewRoute(),
    ... // 省略其它路由注册信息
  } ,
  home: MyHomePage(title: 'Flutter Demo Home Page'),
);

现在我们就完成了路由表的注册。上面的代码中home路由并没有使用命名路由,如果我们也想将home注册为命名路由应该怎么做呢?其实很简单,直接看代码:

MaterialApp(
  title: 'Flutter Demo',
  initialRoute:"/", //名为"/"的路由作为应用的home(首页)
  theme: ThemeData(
    primarySwatch: Colors.blue,
  ),
  //注册路由表
  routes:{
   "new_page":(context) => NewRoute(),
   "/":(context) => MyHomePage(title: 'Flutter Demo Home Page'), //注册首页路由
  } 
);
通过路由名打开新路由页

要通过路由名称来打开新路由,可以使用Navigator 的pushNamed方法:

要通过路由名称来打开新路由,可以使用Navigator 的pushNamed方法:

Navigator 除了pushNamed方法,还有pushReplacementNamed等其他管理命名路由的方法。接下来我们通过路由名来打开新的路由页,修改FlatButtononPressed回调代码,改为:

onPressed: () {
  Navigator.pushNamed(context, "new_page");
  //Navigator.push(context,
  //  MaterialPageRoute(builder: (context) {
  //  return NewRoute();
  //}));  
},
命名路由参数传递

先注册一个路由:

routes:{
   "new_page":(context) => EchoRoute(),
  } ,

在路由页通过RouteSetting对象获取路由参数:

class EchoRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //获取路由参数  
    var args=ModalRoute.of(context).settings.arguments;
    //...省略无关代码
  }
}

在打开路由时传递参数

Navigator.of(context).pushNamed("new_page", arguments: "hi");
适配

假设我们也想将上面路由传参示例中的TipRoute路由页注册到路由表中,以便也可以通过路由名来打开它。但是,由于TipRoute接受一个text 参数,我们如何在不改变TipRoute源码的前提下适配这种情况?其实很简单:

MaterialApp(
  ... //省略无关代码
  routes: {
   "tip2": (context){
     return TipRoute(text: ModalRoute.of(context).settings.arguments);
   },
 }, 
);

路由生成钩子

onGenerateRoute只会对命名路由生效

假设我们要开发一个电商 APP,当用户没有登录时可以看店铺、商品等信息,但交易记录、购物车、用户个人信息等页面需要登录后才能看。为了实现上述功能,我们需要在打开每一个路由页前判断用户登录状态!如果每次打开路由前我们都需要去判断一下将会非常麻烦,那有什么更好的办法吗?路由生成钩子就能解决这个问题

MaterialApp有一个onGenerateRoute属性,它在打开命名路由时可能会被调用,之所以说可能,是因为当调用Navigator.pushNamed(...)打开命名路由时,如果指定的路由名在路由表中已注册,则会调用路由表中的builder函数来生成路由组件;如果路由表中没有注册,才会调用onGenerateRoute来生成路由。onGenerateRoute回调签名如下:

Route<dynamic> Function(RouteSettings settings)

有了onGenerateRoute回调,要实现上面控制页面权限的功能就非常容易:我们放弃使用路由表,取而代之的是提供一个onGenerateRoute回调,然后在该回调中进行统一的权限控制,如:

MaterialApp(
  ... //省略无关代码
  onGenerateRoute:(RouteSettings settings){
      return MaterialPageRoute(builder: (context){
           String routeName = settings.name;
       // 如果访问的路由页需要登录,但当前未登录,则直接返回登录页路由,
       // 引导用户登录;其它情况则正常打开路由。
     }
   );
  }
);

标签:管理,context,Navigator,路由表,Flutter,路由,页面
From: https://blog.csdn.net/nonagontech/article/details/143061466

相关文章

  • Flutter 获取设备网络类型
    前言现在有一个需求,需要能够知道手机端网络类型,如果是WiFi则去使用局域网通信。在这里我选用了connectivity_plus这个库connectivity_plus的平台支持安卓iOS系统苹果系统网络Linux视窗✅✅✅✅✅✅connectivity_plus的APIAPI描述checkConnectivity检查......
  • nvm 一个node.js版本管理工具
    nvm是什么nvm全英文也叫node.jsversionmanagement,是一个nodejs的版本管理工具。nvm和n都是node.js版本管理工具,为了解决node.js各种版本存在不兼容现象可以通过它可以安装和切换不同版本的node.js。下载地址:https://github.com/coreybutler/nvm-windows/releases一、nvm命令......
  • 基于Java+Springboot+Vue开发的鲜牛奶订购管理系统
    项目简介该项目是基于Java+Springboot+Vue开发的鲜牛奶订购管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的鲜牛奶订购管理系统项目,大学生可以在实践中学......
  • jsp二手车市场商户管理系492nz--程序+源码+数据库+调试部署+开发环境
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表商家,店铺信息,二手车辆,租赁申请,退租申请,续租申请,提醒信息开题报告内容一、研究背景随着二手车市场的快速发展,商户管理问题日益凸显。商户信息散乱、管理......
  • jsp儿童疫苗接种管理系统q51zm(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表家长,接种人员,儿童信息,疫苗类型,疫苗信息,入库信息,出库信息,疫苗预约,接种信息,在线反馈,疫苗规划表开题报告内容一、项目背景随着公共卫生意识的提升,儿童......
  • jsp儿童成长信息管理系统t7728--(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、研究背景在信息化时代背景下,儿童成长的记录与管理逐渐趋向于数字化、智能化。家长、教师及教育机构对儿童成长信息的关注日益增强,传统的纸质记......
  • 基于nodejs+vue基于SpringBoot共享单车管理信息平台[开题+源码+程序+论文]计算机毕业
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容一、选题背景关于共享单车管理信息平台的研究,现有研究主要以共享单车的运营模式、市场竞争等为主。专门针对基于SpringBoot框架构建共享单车管理信息平台的研究较少......
  • 基于nodejs+vue基于springboot高校毕业生信息管理系统[开题+源码+程序+论文]计算机毕
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容一、选题背景关于高校毕业生信息管理系统的研究,现有研究主要以传统管理模式为主,专门针对基于springboot技术构建高校毕业生信息管理系统的研究较少。在国内外,高校的......
  • 基于SpringBoot+Vue的学生宿舍管理系统的设计与实现(带文档)
    基于SpringBoot+Vue的学生宿舍管理系统的设计与实现(带文档)开发语言:Java数据库:MySQL技术:SpringBoot+MyBatis+Vue等工具:IDEA/Ecilpse、Navicat、Maven学生宿舍管理系统主要分为三个角色:管理员、宿管员和学生。每个角色都有其独特的功能模块,以满足不同用户的需求。管理......
  • springboot科研项目验收管理系统(11722)
     有需要的同学,源代码和配套文档领取,加文章最下方的名片哦一、项目演示项目演示视频二、资料介绍完整源代码(前后端源代码+SQL脚本)配套文档(LW+PPT+开题报告)远程调试控屏包运行三、技术介绍Java语言SSM框架SpringBoot框架Vue框架JSP页面Mysql数据库IDEA/Eclipse开发四、项......