flutter开发实战-go_router使用

flutter开发实战-go_router使用

在这里插入图片描述

一、go_router介绍与特性

go_router是一个Flutter的第三方声明式路由插件,使用路由器API提供一个方便的、基于url的API,用于在不同屏幕之间导航。可以定义URL模式、使用URL导航、处理深度链接以及许多其他与导航相关的场景。

GoRouter具有许多功能,使导航变得简单明了:

  • 使用模板语法解析路由路径和路由查询(query)参数;
  • 支持单个目标路由展示多个页面(子路由);
  • 重定向:可以基于应用状态跳转到不同的URL,比如用户没有登录时跳转到登录页;
  • 使用 StatefulShellRoute 可以支持嵌套的 Tab 导航;
  • 同时支持 Material 风格和 Cupertino 风格应用;
  • 兼容 Navigator API 。

二、引入go_router

根据自己需要的版本引入对应的版本,在pubspec.yaml加入

  go_router: ^8.2.0

稍后执行flutter pub get命令

三、go_router路由配置

引入插件后,我们需要配置MaterialApp.router的routerConfig

/// The route configuration.
final GoRouter _router = GoRouter(routes: <RouteBase>[GoRoute(path: '/',builder: (BuildContext context, GoRouterState state) {return const HomeScreen();},routes: <RouteBase>[GoRoute(path: 'details',builder: (BuildContext context, GoRouterState state) {return const DetailsScreen();},),],),],
);

配置MaterialApp.router

/// The main app.
class MyApp extends StatelessWidget {/// Constructs a [MyApp]const MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp.router(routerConfig: _router,);}
}

四、go_router路由跳转

如果跳转页面,可以使用content.go

context.go('/details')

4.1、路径参数

GoRouter 的每一个路由都通过 GoRoute对象来配置,可以通过路径参数进行传递相关参数到目标页面。例如路径comment/参数id

GoRoute(path: 'comment/:id',builder: (BuildContext context, GoRouterState state) {String? id = state.pathParameters['id'];print("id:${id}");// Get "id" param from URLreturn CommentScreen(id: id);},),

那么可以通过context.go(’/comment/55555’)传参数

ElevatedButton(onPressed: () => context.go('/comment/55555'),child: const Text('Go to the comment screen'),)

4.2、路径查询参数

可以获取路径的查询参数 URL 路径中的查询(query)参数,例如从/search?keyword=myname中获取search参数。

GoRoute(path: 'search',builder: (BuildContext context, GoRouterState state) {String? keyword = state.queryParameters['keyword'];print("keyword:${keyword}"); // Get "id" param from URLreturn SearchScreen(keyword: keyword);},),

传递参数context.go(’/search?keyword=myName’)目标页面可以得到参数myName

ElevatedButton(onPressed: () => context.go('/search?keyword=myName'),child: const Text('Go to the Search screen'),),

五、添加子路由

子路由,路由匹配支持多个页面,当一个新的页面在旧的页面之上展示时

GoRoute(path: 'details',builder: (BuildContext context, GoRouterState state) {return const DetailsScreen();},routes: <RouteBase>[// Add child routesGoRoute(path: 'sub-details',// NOTE: Don't need to specify "/" character for router’s parentsbuilder: (context, state) {return SubDetailsScreen();},),],),

可以通过context.go(’/details/sub-details’)来进行调用

ElevatedButton(onPressed: () => context.go('/details/sub-details'),child: const Text('Go to the SubDetails screen'),),

六、页面导航

go_router提供多种方式进行跳转

context.goNamed方式

ElevatedButton(onPressed: () => context.goNamed('/details'),child: const Text('Go to the Details screen'),),

七、路由重定向

go_router提供全局重定向,比如在没有登录的用户,需要跳转到登录页面.在 GoRouter 中,可以通过redirect 参数配置重定向.

redirect: (BuildContext context, GoRouterState state) {final isLogin = false;// your logic to check if user is authenticatedif (!isLogin) {return '/login';} else {return null; // return "null" to display the intended route without redirecting}}

八、错误处理(404页面)

go_router为MaterialApp 和CupertinoApp定义了默认的错误页面,也可以通过 errorBuilder 参数自定义错误页面。

errorBuilder: (BuildContext context,GoRouterState state,) {// ErrorPagereturn ErrorScreen();}

九、路由跳转监测

在flutter自带的会有NavigatorObserver,go_router页提供路由跳转监测功能

class MyNavigatorObserver extends NavigatorObserver {@overridevoid didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {print('did push route');}@overridevoid didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {print('did pop route');}
}

在observers中配置

GoRouter(observers: [MyNavigatorObserver()],
...
)

这里只是代码尝试了一下常用功能。还有一些转场动画、嵌套导航等等特性需要去尝试。
可以查看https://juejin.cn/post/7270343009790853172

注意:不同版本的代码有所不同。

测试的完整代码如下

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';void main() {runApp(const MyApp());
}class MyNavigatorObserver extends NavigatorObserver {@overridevoid didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {print('did push route');}@overridevoid didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {print('did pop route');}
}/// The route configuration.
final GoRouter _router = GoRouter(observers: [MyNavigatorObserver()],redirect: (BuildContext context, GoRouterState state) {final isLogin = false; // your logic to check if user is authenticatedif (!isLogin) {return '/login';} else {return null; // return "null" to display the intended route without redirecting}},errorBuilder: (BuildContext context,GoRouterState state,) {// ErrorPagereturn ErrorScreen();},routes: <RouteBase>[GoRoute(path: '/',builder: (BuildContext context, GoRouterState state) {return const HomeScreen();},routes: <RouteBase>[GoRoute(path: 'details',builder: (BuildContext context, GoRouterState state) {return const DetailsScreen();},routes: <RouteBase>[// Add child routesGoRoute(path: 'sub-details',// NOTE: Don't need to specify "/" character for router’s parentsbuilder: (context, state) {return SubDetailsScreen();},),],),GoRoute(path: 'comment/:id',builder: (BuildContext context, GoRouterState state) {String? id = state.pathParameters['id'];print("id:${id}"); // Get "id" param from URLreturn CommentScreen(id: id);},),GoRoute(path: 'search',builder: (BuildContext context, GoRouterState state) {String? keyword = state.queryParameters['keyword'];print("keyword:${keyword}"); // Get "id" param from URLreturn SearchScreen(keyword: keyword);},),],),],
);/// The main app.
class MyApp extends StatelessWidget {/// Constructs a [MyApp]const MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp.router(routerConfig: _router,);}
}/// The home screen
class HomeScreen extends StatelessWidget {/// Constructs a [HomeScreen]const HomeScreen({super.key});@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Home Screen')),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.center,children: [ElevatedButton(onPressed: () => context.goNamed('/details'),child: const Text('Go to the Details screen'),),SizedBox(height: 30,),ElevatedButton(onPressed: () => context.go('/details/sub-details'),child: const Text('Go to the SubDetails screen'),),],),),);}
}/// The details screen
class DetailsScreen extends StatelessWidget {/// Constructs a [DetailsScreen]const DetailsScreen({super.key});@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Details Screen')),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.center,children: [ElevatedButton(onPressed: () => context.go('/comment/55555'),child: const Text('Go to the comment screen'),),SizedBox(height: 30,),ElevatedButton(onPressed: () => context.go('/search?keyword=myName'),child: const Text('Go to the Search screen'),),],),),);}
}/// The details screen
class SubDetailsScreen extends StatelessWidget {/// Constructs a [SubDetailsScreen]const SubDetailsScreen({super.key});@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('SubDetailsScreen Screen')),body: Center(child: ElevatedButton(onPressed: () => context.go('/details'),child: const Text('Go back to the Details screen'),),),);}
}/// The details screen
class CommentScreen extends StatelessWidget {/// Constructs a [DetailsScreen]const CommentScreen({super.key, this.id});final String? id;@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('CommentScreen Screen')),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.center,children: [Text("param id:${id}"),SizedBox(height: 30,),ElevatedButton(onPressed: () => context.go('/'),child: const Text('Go back to the Details screen'),),],)),);}
}/// The Search screen
class SearchScreen extends StatelessWidget {/// Constructs a [DetailsScreen]const SearchScreen({super.key, this.keyword});final String? keyword;@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('SearchScreen Screen')),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.center,children: [Text("param keyword:${keyword}"),SizedBox(height: 30,),ElevatedButton(onPressed: () => context.go('/'),child: const Text('Go back to the details screen'),),],)),);}
}/// The Search screen
class ErrorScreen extends StatelessWidget {/// Constructs a [DetailsScreen]const ErrorScreen();@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('ErrorScreen Screen')),body: Center(child: Container(child: const Text('Error info'),),),);}
}

十、小结

flutter开发实战-go_router使用

学习记录,每天不停进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/50389.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Spring Boot】Spring 的安全框架:Spring Security

Spring 的安全框架&#xff1a;Spring Security 1.Spring Security 初识1.1 核心概念1.2 认证和授权1.2.1 验证&#xff08;authentication&#xff09;1.2.2 授权&#xff08;authorization&#xff09; 1.3 模块 2.核心类2.1 Securitycontext2.2 SecurityContextHolder2.2.1 …

Python字符串处理技巧:一个小技巧竟然能省下你一半时间!

获取Pyhon及副业知识&#xff0c;关注公众号【软件测试圈】 效率翻倍的秘密&#xff1a;Python字符串操作的5个惊人技巧 在Python编程中&#xff0c;字符串处理在数据分析、Web开发、自动化脚本等多个领域都有广泛应用。Python提供了一系列强大的字符串处理函数&#xff0c;能够…

前端工程化11-webpack常见插件

1、webpack的插件Plugin 刚才我们也讲解了下&#xff0c;我们对webpack路径的一个处理&#xff0c;处理的话包括别名的配置&#xff0c;模块是如何找到并加载的&#xff0c;总的来说到现在webpack这个配置到现在来说还是相当的麻烦的&#xff0c;但是目前来说我们讲的这些东西…

前端工程化-vue项目创建

可以使用html、css、javascpript ,以及使用vue、axios等技术搭建前端页面&#xff0c;但效率低、结构乱。 实际前端开发&#xff1a; 前端工程化开发步骤&#xff1a; 一、环境准备 1.安装NodeJS2. 安装vue-cli 二、创建Vue项目 有两种方式创建&#xff0c;一般采用第二种图…

MMCV1.6.0之Runner/Hook/OptimizerHook(反向传播+参数更新)、Fp16OptimizerHook、自定义优化器与config设置

OptimizerHook 这段代码定义了一个名为 OptimizerHook 的类&#xff0c;它是一个用于优化器的自定义操作钩子。该钩子包含了一些用于梯度裁剪和检测异常参数的操作。这对于在深度学习训练过程中优化模型的性能和调试模型非常有用。 类的定义 OptimizerHook 类继承自 Hook&…

documents4j 将word转pdf文件,本地(Windows)测试没问题,部署到服务器(centos)报错

问题 报错如下&#xff1a; 代码 首先要保证你的Java代码没问题&#xff0c;可以参考下面代码 maven依赖 <!--documents4j--> <dependency><groupId>com.documents4j</groupId><artifactId>documents4j-local</artifactId><versi…

解决mysql事件调度器重启服务后自动失效的问题

前段时间为通过mysql事件生成测试数据&#xff0c;今天发现数据在10:57后停止了CREATE EVENT IF NOT EXISTS insert_random_data ON SCHEDULE EVERY 10 SECOND DO INSERT INTO test (createtime, random_number) VALUES (NOW(), FLOOR(RAND() * 100));检查事件状态&#…

C++String类的手撕实现

目录 构造函数 提前准备工作&#xff1a; 有参构造 析构函数 c_str 无参构造&#xff1a; 无参和有参的结合 operater[]的实现 简易版的迭代器 begin end 原因&#xff1a; reserve 思想步骤 获取_capacity 和 _size 测试 push_back 思想步骤 append insert…

平安养老险广西分公司开展7.8公益健步行活动

近日&#xff0c;平安养老保险股份有限公司&#xff08;以下简称“平安养老险”&#xff09;广西分公司在南宁邕江沿岸开展“7.8”公益健步行活动&#xff0c;在分公司班子的号召下&#xff0c;各部门内外勤员工均踊跃参与。 员工们沿途随手捡拾垃圾&#xff0c;传递积极、绿色…

就在刚刚,中国 IMO 奥数遗憾地失去了第一名的宝座,连续五年的统治地位被美国队所终结。

&#x1f431; 个人主页&#xff1a;TechCodeAI启航&#xff0c;公众号&#xff1a;TechCodeAI &#x1f64b;‍♂️ 作者简介&#xff1a;2020参加工作&#xff0c;专注于前端各领域技术&#xff0c;共同学习共同进步&#xff0c;一起加油呀&#xff01; &#x1f4ab; 优质专…

Vue3开源Tree组件研发:节点勾选支持v-model

自研Tree组件有两个原因&#xff1a;1. 目前开源UI对Tree组件的用户API不太友好&#xff0c;2. 提升Vue3组件自研能力。 目前已实现的功能见上面思维导图。想象Tree组件的一个使用场景&#xff1a;后台管理员通过Tree组件来完成用户角色授权&#xff0c;同时支持对权限进行新增…

Spring中使用到的设计模式及其源码分析

前言 众所周知&#xff0c;Spring框架是一个强大而灵活的开发框架。这不&#xff0c;上次的面试刚问到这些&#xff0c;没防住&#xff01;&#xff01;&#xff01;因此下来总结一下。这篇文章主要介绍Spring中使用到的设计模式&#xff0c;自己做个面试复盘&#xff0c;同时…

Spring Security 原理

Spring Security是一个功能强大且广泛使用的身份验证和授权框架&#xff0c;专为保护Java应用程序的安全性而设计。它提供了一套可配置的安全性规则和机制&#xff0c;用于对应用程序的资源进行访问控制和保护。以下是Spring Security的主要原理&#xff1a; 1. 过滤器链&…

引领安全新风尚:WT2605/WT2003H芯片方案赋能电动汽车,打造智能低速安全报警器"

电动汽车低速报警器(AVAS)方案可采用WT2605或WT2003H方案芯片,可实现当车辆时速低于设定值(如20Km/h),报警器会发出类似发动机加速减速的声音,倒档时装置也会发出倒车警示,在嘈杂的城市环境中帮助提升行人对驶近的电动汽车的感知,降低行人、骑行者和弱势群体面临的风险。 WT26…

十分钟带你入门Go语言(Golang)开发

概述 Go语言是由 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态强类型、编译型语言。Go语言的设计目标是将静态语言的安全性和性能与动态语言的易用性相结合。Go语言在语言层面提供了对协程的支持&#xff0c;特别适合编写高并发的项目。随着使用Go语言…

基于opencv的答题卡识别

文章目录 一、背景需求二、处理步骤图片预处理检测到答题卡轮廓透视变换找每个圆圈的轮廓轮廓排序判断是否答题正确 一、背景需求 传统的手动评分方法耗时且容易出错&#xff0c;自动化评分可以可以显著提高评分过程的速度和准确性、减少人工成本。 答题卡图片处理效果如下&am…

想出国?去外企?建议网工无脑冲思科认证。

近年来&#xff0c;国内职场竞争愈发激烈&#xff0c;内卷现象严重&#xff0c;大部分人都面临着巨大的就业压力&#xff0c;或是找工作无门、或是中年危机悄然来临&#xff0c;时刻担心被职场优化。 在这样的背景下&#xff0c;出国或进入外企工作&#xff0c;成为了许多人寻…

[JavaScript] 动态获取方法参数名

JavaScript&#xff08;简称“JS”&#xff09;是一种具有函数优先的轻量级&#xff0c;解释型或即时编译型的编程语言。虽然它是作为开发Web页面的脚本语言而出名&#xff0c;但是它也被用到了很多非浏览器环境中&#xff0c;JavaScript基于原型编程、多范式的动态脚本语言&am…

Optional类的使用 java8(附代码)

&#x1f370; 个人主页:_小白不加班__ &#x1f35e;文章有不合理的地方请各位大佬指正。 &#x1f349;文章不定期持续更新&#xff0c;如果我的文章对你有帮助➡️ 关注&#x1f64f;&#x1f3fb; 点赞&#x1f44d; 收藏⭐️ 文章目录 一、什么是Optional&#xff1f;二、…

科研绘图系列:R语言和弦图 (Chord diagram)

介绍 和弦图(Chord Diagram)是一种用于展示多个实体之间相互关系的数据可视化方法。它通常用于表示网络或系统中不同节点(实体)之间的连接强度或流量。和弦图由一个圆形布局组成,每个节点在圆周上占据一个扇形区域,节点之间的连接通过圆内的线条(和弦)来表示。 特点:…