二、Flutter必学!Getx路由管理
什么是 GetX?
一个简单、高效、强大的管理状态、路由管理库
学习目标
- 掌握使用
GetX
管理路由 - 掌握使用
GetX
路由的中间件 - 学会配置路由
GetX路由管理优点
- 使用简洁、逻辑清晰(Controller)
- 功能强大,多种使用形态
安装
先安装get
依赖到你的pubspec.yaml
文件中
dependencies:
get:
一、路由的用法
使用路由之前需要把MaterialApp
换成GetMaterialApp
,这十分重要!
// MaterialApp( 之前是这样
GetMaterialApp(
home: MyHome(),
)
1.普通路由导航
1.1 to
进入新页面
从当前页面进入到一个新页面,to
接收一个页面组件
Get.to(NextScreen());
1.2 back
回退操作
通常会用Navigator.pop(context)
关闭的东西。
使用场景: 关闭Dialogs
、SnackBars
或者退出当前页面。
Get.back();
1.3 off
类似于replace
操作
它会替拿当新页面换掉当前页面,并且新页面左上角没有返回按钮,
使用场景: 登录页、SplashScreens之类的
Get.off(NextScreen());
1.4 offAll
清空历史路由
该方法会清空我们之前打开过的页面,只留下新的页面
使用场景: 购物车、投票之类的
Get.offAll(NextScreen());
1.5 接收新返回信息
var data = await Get.to(Payment());
2.别名路由导航
你不必有太多的学习压力,别名路由十分简单
// toNamed 导航到下一个页面
Get.toNamed("/NextScreen");
// 浏览并删除前一个页面
Get.offNamed("/NextScreen");
// 浏览并删除所有以前的页面
Get.offAllNamed("/NextScreen");
3.路由传参数
有3种传递参数的方法:
arguments
传参- 问号传参(跟
URL
地址一样) - 动态路由(
/:xxx
)
3.1 arguments
传参
发送任何参数都可以接收,不论是什么类型!甚至是类的实例!
Get.toNamed("/NextScreen", arguments: '这是一个字符串参数');
在页面类或控制器上接收:
print(Get.arguments); // out: 这是一个字符串参数
3.2问号传参
只能接收字符串
Get.offAllNamed("/NextScreen?device=phone&id=111&name=liang");
通过Get.parameters
获取值
print(Get.parameters['id']); // out: 111
print(Get.parameters['name']); // out: liang
void main() {
runApp(
GetMaterialApp(
initialRoute: '/',
getPages: [
GetPage(
name: '/',
page: () => MyHomePage(),
),
GetPage(
name: '/profile/',
page: () => MyProfile(),
),
GetPage(
name: '/profile/:user',
page: () => UserProfile(),
),
],
)
);
}
3.3动态路由
咱们在配置表中配置动态路由,他是通过Get.parameters
接收
void main() {
runApp(
GetMaterialApp(
initialRoute: '/',
getPages: [
GetPage(
name: '/',
page: () => MyHomePage(),
),
GetPage(
name: '/profile/', // 没值匹配就写 / 在后面
page: () => MyProfile(),
),
GetPage(
name: '/profile/:user', // 如果有值 /:xxx 在后面
page: () => UserProfile(),
),
GetPage(
name: '/third',
page: () => Third(),
transition: Transition.cupertino
),
],
)
);
}
发送别名路由数据:
Get.toNamed("/profile/34954");
// 在第二个页面上,通过参数获取数据
print(Get.parameters['user']);
// out: 34954
混合发送参数:
Get.toNamed("/profile/34954?flag=true");
// 在第二个页面上,通过参数获取数据
print(Get.parameters['user']);
print(Get.parameters['flag']);
// out: 34954 true
4.路由中间件
除了可以监听路由外,还可以监听每个页面上的SnackBars
、 Dialogs
和Bottomsheets
。
有两种方式可以实现中间件:
GetMaterialApp
的routingCallback
MaterialApp
的navigatorObservers
(相对麻烦)
中间件:字面意思就是在中间处理一些事件
4.1routingCallback
通过监听Get
事件触发回调,我们可以基于GetMaterialApp
的routingCallback
参数实现。
GetMaterialApp(
routingCallback: (routing) {
if(routing.current == '/user') {
openAds();
}
}
)
4.2navigatorObservers
如果没有使用GetMaterialApp
,那么可以使用API来附加Middleware
观察器。
void main() {
runApp(
MaterialApp(
onGenerateRoute: Router.generateRoute,
initialRoute: "/",
navigatorKey: Get.key,
navigatorObservers: [ // 基于这个来观察路由变化
GetObserver(MiddleWare.observer), // HERE !!!
],
),
);
}
4.2.1创建一个MiddleWare类
class MiddleWare {
static observer(Routing routing) {
if (routing.current == '/second' && !routing.isSnackbar) {
Get.snackbar("Hi", "You are on second route");
} else if (routing.current =='/third'){
print('last route called');
}
}
}
二、GetMaterialApp
的常用配置
使用GetMaterialApp
定义路由。
void main() {
runApp(
GetMaterialApp(
// 初始路径
initialRoute: '/',
// 404页面
unknownRoute: GetPage(name: '/notfound', page: () => UnknownRoutePage()),
// 中间件
routingCallback: (routing) {
if(routing.current == '/user') {
openAds();
}
},
// 路由配置表
getPages: [
GetPage(name: '/', page: () => MyHomePage()),
GetPage(name: '/second', page: () => Second()),
],
)
);
}
三、免context
导航
SnackBars
以前你可能需要这样去写一个SnackBars
功能:
final snackBar = SnackBar(
content: Text('Hi!'),
action: SnackBarAction(
label: 'I am a old and ugly snackbar :(',
onPressed: (){}
),
);
// 在小组件树中找到脚手架并使用它显示一个SnackBars。
Scaffold.of(context).showSnackBar(snackBar);
但是使用Get
后可以随处使用它!
Get.snackbar('Hi', 'i am a modern snackbar');
// 定制你的需求,随处可使用
Get.snackbar(
"Hey i'm a Get SnackBar!", // title
"It's unbelievable! I'm using SnackBar without context, without boilerplate, without Scaffold, it is something truly amazing!", // message
icon: Icon(Icons.alarm),
shouldIconPulse: true,
onTap:(){},
barBlur: 20,
isDismissible: true,
duration: Duration(seconds: 3),
);
Dialog
// 定制一个 Dialog
Get.dialog(YourDialogWidget());
打开默认Dialogs
Get.defaultDialog(
onConfirm: () => print("Ok"),
middleText: "Dialog made in 3 lines of code"
);
BottomSheets
Get.bottomSheet(
Container(
child: Wrap(
children: <Widget>[
ListTile(
leading: Icon(Icons.music_note),
title: Text('Music'),
onTap: () {}
),
ListTile(
leading: Icon(Icons.videocam),
title: Text('Video'),
onTap: () {},
),
],
),
)
);
四、嵌套导航
Get
的路由嵌套非常简单,不需要context
而是通过id
寻找导航栈
Navigator(
key: Get.nestedKey(1), // 创建一个key
initialRoute: '/',
onGenerateRoute: (settings) {
if (settings.name == '/') {
return GetPageRoute(
page: () => Scaffold(
appBar: AppBar(
title: Text("Main"),
),
body: Center(
child: TextButton(
color: Colors.blue,
onPressed: () {
Get.toNamed('/second', id:1); // 按照key以及路由来路径来导航,如果没找到会报错
},
child: Text("Go to second"),
),
),
),
);
} else if (settings.name == '/second') {
return GetPageRoute(
page: () => Center(
child: Scaffold(
appBar: AppBar(
title: Text("Main"),
),
body: Center(
child: Text("second")
),
),
),
);
}
}
),
注意:尽量少用这种方式,因为在内存中维持多个导航堆栈比较消耗内存
转载自:https://juejin.cn/post/7227486312340095033