当前位置:   article > 正文

Flutter中GetX的用法(路由管理)

Flutter中GetX的用法(路由管理)

目录

前言

一.安装

二.从一个计时器开始

三.Getx路由管理

1.普通路由导航

1.导航到新的页面

2.关闭SnackBars、Dialogs、BottomSheets或任何你通常会用Navigator.pop(context)关闭的东西

3.进入下一个页面,但没有返回上一个页面的选项(用于SplashScreens,登录页面等)

4.进入下一个界面并取消之前的所有路由

5.要导航到下一条路由,并在返回后立即接收或更新数据

2.别名路由导航

1.导航到下一个页面

2.浏览并删除前一个页面

3.浏览并删除所有以前的页面

4.别名路由传值

5.动态网页链接

3.中间件

4.免context导航

1.SnackBars

2.Dialogs

3.BottomSheets

四.文章中的完整demo


前言

        正如Get官方介绍,GetX 是 Flutter 上的一个轻量且强大的解决方案:高性能的状态管理、智能的依赖注入和便捷的路由管理。GetX 有3个基本原则:

        性能: GetX 专注于性能和最小资源消耗。

        效率: GetX 的语法非常简捷,并保持了极高的性能,能极大缩短你的开发时长。

        结构: GetX 可以将界面、逻辑、依赖和路由之间低耦合,逻辑更清晰,代码更容易维护。

        这篇文章主要是介绍下GetX的用法。

一.安装

        目前get最新的版本是4.6.6。安装方式如下:

dependencies:
  get: ^4.6.6

二.从一个计时器开始

        但我们创建一个flutter工程的时候,系统会生成一个计时器的示例代码,代码大致如下(我删除了部分注释代码):

  1. import 'package:flutter/material.dart';
  2. void main() {
  3. runApp(const MyApp());
  4. }
  5. class MyApp extends StatelessWidget {
  6. const MyApp({super.key});
  7. @override
  8. Widget build(BuildContext context) {
  9. return MaterialApp(
  10. title: 'Flutter Demo',
  11. theme: ThemeData(
  12. colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
  13. useMaterial3: true,
  14. ),
  15. home: const MyHomePage(title: 'Flutter Demo Home Page'),
  16. );
  17. }
  18. }
  19. class MyHomePage extends StatefulWidget {
  20. const MyHomePage({super.key, required this.title});
  21. final String title;
  22. @override
  23. State<MyHomePage> createState() => _MyHomePageState();
  24. }
  25. class _MyHomePageState extends State<MyHomePage> {
  26. int _counter = 0;
  27. void _incrementCounter() {
  28. setState(() {
  29. _counter++;
  30. });
  31. }
  32. @override
  33. Widget build(BuildContext context) {
  34. return Scaffold(
  35. appBar: AppBar(
  36. backgroundColor: Theme.of(context).colorScheme.inversePrimary,
  37. title: Text(widget.title),
  38. ),
  39. body: Center(
  40. child: Column(
  41. mainAxisAlignment: MainAxisAlignment.center,
  42. children: <Widget>[
  43. const Text(
  44. 'You have pushed the button this many times:',
  45. ),
  46. Text(
  47. '$_counter',
  48. style: Theme.of(context).textTheme.headlineMedium,
  49. ),
  50. ],
  51. ),
  52. ),
  53. floatingActionButton: FloatingActionButton(
  54. onPressed: _incrementCounter,
  55. tooltip: 'Increment',
  56. child: const Icon(Icons.add),
  57. ), // This trailing comma makes auto-formatting nicer for build methods.
  58. );
  59. }
  60. }

        主要功能是点击+按钮,每次计时器的个数+1.点击按钮之后,调用setState方法刷新_counter变量。

        下面我们看一下如何使用getx来实现上述的功能:

        第一步:把系统的MaterialApp改成GetMaterialApp:

void main() => runApp(GetMaterialApp(home: Home()));

        第二步:创建业务类,我们把_counter变量放在Controller类中:

class Controller extends GetxController{
  var counter = 0.obs;
  increment() => counter++;
}

        第三步:使用StatelessWidget代替StatefulWidget,节省下内存。修改之后的完整代码如下:

  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. void main() {
  4. runApp(const MyApp());
  5. }
  6. class MyApp extends StatelessWidget {
  7. const MyApp({super.key});
  8. @override
  9. Widget build(BuildContext context) {
  10. return GetMaterialApp(
  11. title: 'Flutter Demo',
  12. theme: ThemeData(
  13. colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
  14. useMaterial3: true,
  15. ),
  16. home: const MyHomePage(title: 'Flutter Demo Home Page'),
  17. );
  18. }
  19. }
  20. class Controller extends GetxController{
  21. var counter = 0.obs;
  22. incrementCounter()=>counter++;
  23. }
  24. class MyHomePage extends StatelessWidget {
  25. const MyHomePage({super.key, required this.title});
  26. final String title;
  27. @override
  28. Widget build(BuildContext context) {
  29. final Controller controller = Get.put(Controller());
  30. return Scaffold(
  31. appBar: AppBar(
  32. backgroundColor: Theme.of(context).colorScheme.inversePrimary,
  33. title: Text(title),
  34. ),
  35. body: Center(
  36. child: Column(
  37. mainAxisAlignment: MainAxisAlignment.center,
  38. children: <Widget>[
  39. const Text(
  40. 'You have pushed the button this many times:',
  41. ),
  42. Obx(() => Text(
  43. '${controller.counter}',
  44. style: Theme.of(context).textTheme.headlineMedium,
  45. )),
  46. ],
  47. ),
  48. ),
  49. floatingActionButton: FloatingActionButton(
  50. onPressed: (){
  51. controller.incrementCounter();
  52. },
  53. tooltip: 'Increment',
  54. child: const Icon(Icons.add),
  55. ), // This trailing comma makes auto-formatting nicer for build methods.
  56. );
  57. }
  58. }

三.Getx路由管理

1.普通路由导航

1.导航到新的页面

        假如我们有一个新页面NextScreenPage,代码如下:

  1. import 'package:flutter/material.dart';
  2. class NextScreenPage extends StatelessWidget {
  3. const NextScreenPage({super.key});
  4. @override
  5. Widget build(BuildContext context) {
  6. return Scaffold(
  7. appBar: AppBar(
  8. backgroundColor: Theme.of(context).colorScheme.inversePrimary,
  9. title: const Text("新页面"),
  10. ),
  11. body: Container(
  12. ), // This trailing comma makes auto-formatting nicer for build methods.
  13. );
  14. }
  15. }

        从当前页面跳转到NextScreenPage页面,代码如下:

Get.to(()=>NextScreen());

2.关闭SnackBars、Dialogs、BottomSheets或任何你通常会用Navigator.pop(context)关闭的东西

        还是以上面的代码为例,我们添加一个返回按钮,点击返回按钮的时候,回到当前页面。主需要在按钮的点击事件中添加如下代码即可:

Get.back();

        NextScreenPage页面完整代码如下:

  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. class NextScreenPage extends StatelessWidget {
  4. const NextScreenPage({super.key});
  5. @override
  6. Widget build(BuildContext context) {
  7. return Scaffold(
  8. appBar: AppBar(
  9. backgroundColor: Theme.of(context).colorScheme.inversePrimary,
  10. title: const Text("新页面"),
  11. ),
  12. body: Center(
  13. child: ElevatedButton(onPressed: (){
  14. Get.back();
  15. }, child: const Text("返回上一个页面")),
  16. ), // This trailing comma makes auto-formatting nicer for build methods.
  17. );
  18. }
  19. }
3.进入下一个页面,但没有返回上一个页面的选项(用于SplashScreens,登录页面等)

        主要的代码如下:

Get.off(()=>const NormalRoutePage(title: "主页面"));

        这里我们模拟一个登陆页面的场景,假设当前页面(NormalRoutePage)有一个按钮,点击按钮之后,我们跳转到登陆页面(LoginPage),登陆成功之后,进入个人中心页面(ProfilePage),这个时候,个人中心页面有个返回按钮,我们点击返回按钮的时候回到主页面,主要的代码如下:

        登陆页面代码如下:

  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. import 'package:getx_demos/route_manager/login/profile_page.dart';
  4. class LoginPage extends StatelessWidget {
  5. const LoginPage({super.key});
  6. @override
  7. Widget build(BuildContext context) {
  8. return Scaffold(
  9. appBar: AppBar(
  10. backgroundColor: Theme.of(context).colorScheme.inversePrimary,
  11. title: const Text("登陆页面"),
  12. ),
  13. body: Center(
  14. child: ElevatedButton(onPressed: (){
  15. Get.to(()=>const ProfilePage());
  16. }, child: const Text("点击进入个人中心页面")),
  17. ), // This trailing comma makes auto-formatting nicer for build methods.
  18. );
  19. }
  20. }

        个人中心页面代码如下:

  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. import 'package:getx_demos/route_manager/normal_route_page.dart';
  4. class ProfilePage extends StatelessWidget {
  5. const ProfilePage({super.key});
  6. @override
  7. Widget build(BuildContext context) {
  8. return Scaffold(
  9. appBar: AppBar(
  10. backgroundColor: Theme.of(context).colorScheme.inversePrimary,
  11. title: const Text("个人中心页面"),
  12. ),
  13. body: Center(
  14. child: ElevatedButton(onPressed: (){
  15. Get.off(const NormalRoutePage(title: "主页面"));
  16. }, child: const Text("返回主页面")),
  17. ), // This trailing comma makes auto-formatting nicer for build methods.
  18. );
  19. }
  20. }
4.进入下一个界面并取消之前的所有路由

Get.offAll(NextScreen());

5.要导航到下一条路由,并在返回后立即接收或更新数据

        假设当前页面是SecondPage,当我们跳转按钮之后跳转到ThirdPage,按钮的点击事件中我们使用下面的代码获取ThirdPage回传的值:

var data = await Get.to(const ThirdPage());        

        SecondPage页面代码如下:

  1. import 'package:getx_demos/route_manager/login/third_page.dart';
  2. class SecondPage extends StatelessWidget {
  3. const SecondPage({super.key});
  4. @override
  5. Widget build(BuildContext context) {
  6. return Scaffold(
  7. appBar: AppBar(
  8. backgroundColor: Theme.of(context).colorScheme.inversePrimary,
  9. title: const Text("回调传值"),
  10. ),
  11. body: Column(
  12. children: [
  13. Center(
  14. child: ElevatedButton(onPressed: () async {
  15. var data = await Get.to(const ThirdPage());
  16. debugPrint("下个页面回调值:$data");
  17. Get.to(()=>const ThirdPage());
  18. }, child: const Text("跳转Third页面")),
  19. ),
  20. ],
  21. ), // This trailing comma makes auto-formatting nicer for build methods.
  22. );
  23. }
  24. }

        ThirdPage页面代码如下:

  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. class ThirdPage extends StatelessWidget {
  4. const ThirdPage({super.key});
  5. @override
  6. Widget build(BuildContext context) {
  7. return Scaffold(
  8. appBar: AppBar(
  9. backgroundColor: Theme.of(context).colorScheme.inversePrimary,
  10. title: const Text("Third"),
  11. ),
  12. body: Column(
  13. children: [
  14. const Text("第二个页面传过来的值:"),
  15. Center(
  16. child: ElevatedButton(onPressed: (){
  17. Get.back(result: "555555");
  18. }, child: const Text("返回主页面")),
  19. ),
  20. ],
  21. ), // This trailing comma makes auto-formatting nicer for build methods.
  22. );
  23. }
  24. }

2.别名路由导航

        Get支持别名路由,使用别名路由的时候,我们需要在GetMaterialApp定义一下,假如我们有一个NextScreenPage页面,使用别名路由的时候,代码定义如下:

  1. class MyApp extends StatelessWidget {
  2. const MyApp({super.key});
  3. @override
  4. Widget build(BuildContext context) {
  5. return GetMaterialApp(
  6. title: 'Flutter Demo',
  7. initialRoute: "/",
  8. getPages: [
  9. GetPage(name: "/next_screen", page: ()=>const NextScreenPage()),
  10. ],
  11. theme: ThemeData(
  12. colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
  13. useMaterial3: true,
  14. ),
  15. home: const MyHomePage(title: 'Flutter Demo Home Page'),
  16. );
  17. }
  18. }
1.导航到下一个页面

Get.toNamed("/next_screen");

2.浏览并删除前一个页面

Get.offNamed("/next_screen");

3.浏览并删除所有以前的页面

Get.offAllNamed("/next_screen");

4.别名路由传值

Get.toNamed("/rename_main",arguments: "Getx route manager");

5.动态网页链接

        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']} ");

3.中间件

        如果你想通过监听Get事件来触发动作,你可以使用routingCallback来实现。

GetMaterialApp( routingCallback: (routing) { if(routing.current == '/second'){ openAds(); } } )

4.免context导航

        如果你想通过监听Get事件来触发动作,你可以使用routingCallback来实现。

1.SnackBars

        GetX创建一个SnackBars代码如下:

Get.snackbar('SnackBar', '我是SnackBar');

2.Dialogs

        打开默认Dialogs:

Get.defaultDialog(
onConfirm: () => debugPrint("Ok"),
middleText: "我是Dialog"
);

3.BottomSheets

        Get.bottomSheet类似于showModalBottomSheet,但不需要context:

  1. Get.bottomSheet(
  2. Wrap(
  3. children: <Widget>[
  4. ListTile(
  5. leading: const Icon(Icons.music_note),
  6. title: const Text('Music'),
  7. onTap: () {}
  8. ),
  9. ListTile(
  10. leading: const Icon(Icons.videocam),
  11. title: const Text('Video'),
  12. onTap: () {},
  13. ),
  14. ],
  15. )
  16. );

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")
            ),
          ),
        ),
      );
    }
  }
),

四.文章中的完整demo

        本文实例中的demo地址。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/257341
推荐阅读
相关标签
  

闽ICP备14008679号