前言
一.安装
二.Getx路由管理
1.普通路由导航
1.导航到新的页面
1.返回上一个页面
2.关闭其它Widget
3.进入下一个页面,但没有返回上一个页面的选项
4.进入下一个界面并取消之前的所有路由
5.跳转到下一个页面并接收会传值
2.别名路由导航
1.别名路由导航
1.导航到下一个页面
2.浏览并删除前一个页面
3.浏览并删除所有以前的页面
4.未定义导航
2.别名路由传值并传值
3.动态网页链接
4.中间件
4.免context导航
1.SnackBars
2.Dialogs
3.BottomSheets
3.嵌套导航
4.完整demo
正如Get官方介绍,GetX 是 Flutter 上的一个轻量且强大的解决方案:高性能的状态管理、智能的依赖注入和便捷的路由管理。GetX 有3个基本原则:
性能: GetX 专注于性能和最小资源消耗。
效率: GetX 的语法非常简捷,并保持了极高的性能,能极大缩短你的开发时长。
结构: GetX 可以将界面、逻辑、依赖和路由之间低耦合,逻辑更清晰,代码更容易维护。
这篇文章主要是介绍下GetX的用法。
目前get最新的版本是4.6.6。安装方式如下:
安装好get之后,最简单的配置就是在你的MaterialApp前面加上 "Get",就可以把它变成GetMaterialApp,下面就可以尽情的使用你的GetX吧。
GetMaterialApp( // Before: MaterialApp(
home: MyHomePage(),
)
假如我们有一个新页面NextScreenPage,代码如下:
import 'package:flutter/material.dart';
class NextScreenPage extends StatelessWidget {
const NextScreenPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text("新页面"),
),
body: Container(
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
效果图如下:
图1.跳转新页面
Get.back可以用来关闭SnackBars、Dialogs、BottomSheets或任何你通常会用Navigator.pop(context)关闭的东西。
我们可以下面的代码来实现相应的功能。
还是以上面的代码为例,我们在NextScreen中点击返回按钮的时候,回到当前页面。直接调用Get.back即可:
Get.back();
图2.返回上一页
Get.back关闭SnackBars、Dialogs、BottomSheets或任何你通常会用Navigator.pop(context)关闭的东西。
我们以SnackBar为例,在下面的例子中,我们点击展示SnackBar按钮,StanackBar显示10秒钟,点击关闭SnackBar按钮的时候,调用Get.back即可关闭SnackBar。
当然其它的Widget例如Dialogs、BottomSheets或任何你通常会用Navigator.pop(context)关闭的东西你都可以调用Get.back来实现。
图3.关闭SnackBar的例子
这种场景用于SplashScreens,登录页面等。例如我们第一次进入用户引导页面,下一次直接进入主页。
以下面的实例为例,我们点击按钮进入下一个页面,然后点击返回按钮直接返回app主页。
Get.off(const NextScreenPage());
图4.导航并销毁上一个页面
这个在购物车、投票和测试中很有用。
如下图5所示,我们点击跳转按钮之后,直接取消之前的所有页面,实现代码如下:
Get.off(const NextScreenPage());
图5.导航到下一个页面并取消所有路由
要导航到下一条路由,并在返回后立即接收或更新数据。
var data = await Get.to(const NextScreenPage());
在另一个页面上,发送前一个路由的数据。
Get.back(result: 'success');
效果如下:
图6.跳转到下一个页面并接收下一页面回传值
Get支持别名路由,使用别名路由的时候,我们需要在GetMaterialApp定义一下,假如我们有一个NextScreenPage页面,使用别名路由的时候,代码定义如下:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:getx_route_management/next_screen_page.dart';
import 'home_page.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
initialRoute: '/',
getPages: [
GetPage(name: '/NextScreen', page: () => const NextScreenPage()),
],
home: const MyHomePage(),
);
}
}
Get.toNamed("/next_screen");
Get.offNamed("/next_screen");
Get.offAllNamed("/NextScreen");
为了防止我们导航到未定义的页面,我们可以在GetMaterialApp中定义unknownRoute页面。
import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:getx_route_management/404_page.dart'; import 'package:getx_route_management/next_screen_page.dart'; import 'home_page.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return GetMaterialApp( title: 'Flutter Demo', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), unknownRoute: GetPage(name: '/not_found', page: ()=>const UnknownRoutePage()), initialRoute: '/', getPages: [ GetPage(name: '/NextScreen', page: () => const NextScreenPage()), ], home: const MyHomePage(), ); } }
这样当我们通过别名路由方式跳转的时候,如果路由的名称写错了,会自动导航到我们定义的404路由页面。
图7.404路由页面
只要发送你想要的参数即可。Get在这里接受任何东西,无论是一个字符串,一个Map,一个List,甚至一个类的实例。
Get.toNamed("/NextScreen", arguments: 'Get is the best');
在你的类或控制器上:
print(Get.arguments);
//print out: Get is the best
Get提供高级动态URL,就像在Web上一样。
Get.offAllNamed("/NextScreen?device=phone&id=354&name=Enzo");
第二个页面获取数据:
debugPrint("id = ${Get.parameters['id']} ");
debugPrint("device = ${Get.parameters['device']} ");
debugPrint("name = ${Get.parameters['name']} ");
受制于文章篇幅,这里专门写了一篇Getx鉴权的博客,有兴趣的同学们可以查看下。
使用GetX我们可以避免使用Flutter非常多的代码去实现SnackBar、Dialogs、BottomSheets。
下面我们看具体的用法:
GetX创建一个SnackBars代码如下:
Get.snackbar('SnackBar', '我是SnackBar');
图7.Getx免context导航
OK,就这么一行代码,我们就轻松的实现了SnackBar。
我们看看Flutter怎么实现这个功能:
用Flutter创建一个简单的SnackBar,你必须获得Scaffold的context,或者你必须使用一个GlobalKey附加到你的Scaffold上。
final snackBar = SnackBar(
content: Text('Hi!'),
action: SnackBarAction(
label: 'I am a old and ugly snackbar :(',
onPressed: (){}
),
);
// 在小组件树中找到脚手架并使用它显示一个SnackBars。
Scaffold.of(context).showSnackBar(snackBar);
这么一对比,看看Getx提高了多少效率。
当然这里仅仅是演示getX的用法,具体使用SnackBar的定制,您可以看一下它的源码。
同样我们使用defaultDialog和dialog也不需要context。
仅仅需要一行代码即可。
打开Dialogs:
Get.dialog(YourDialogWidget());
打开默认Dialogs代码如下:
Get.defaultDialog(
onConfirm: () => debugPrint("Ok"),
middleText: "我是Dialog"
);
图8.免dialogs导航
Get.bottomSheet类似于showModalBottomSheet,但不需要context:
Get.bottomSheet(
Wrap(
children: <Widget>[
ListTile(
leading: const Icon(Icons.music_note),
title: const Text('Music'),
onTap: () {}
),
ListTile(
leading: const Icon(Icons.videocam),
title: const Text('Video'),
onTap: () {},
),
],
)
);
效果图如下:
图9.免BottomSheets导航
5.嵌套导航
Get让Flutter的嵌套导航更加简单。 你不需要context,而是通过Id找到你的导航栈。
Navigator(
key: Get.nestedKey(1), // create a key by index
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); // navigate by your nested route by index
},
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")
),
),
),
);
}
}
),
Get让Flutter的嵌套导航更加简单。 你不需要context,而是通过Id找到你的导航栈。
注意:创建平行导航堆栈可能是危险的。理想的情况是不要使用NestedNavigators,或者尽量少用。如果你的项目需要它,请继续,但请记住,在内存中保持多个导航堆栈可能不是一个好主意(消耗RAM)。
看看它有多简单:
Navigator(
key: Get.nestedKey(1), // create a key by index
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); // navigate by your nested route by index
},
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")
),
),
),
);
}
}
),
本文用到的demo在这里。