Flutter插件Get(3):路由管理篇.md

一、前言

GetX 为我们封装了 Navigation ,无需 context 可进行跳转,使用 GetX 进行路由跳转非常的简单,只需要调用Get.to()等即可进行路由跳转。以下是其一些用法:

方法 功能
Get.to() 跳转新页面
Get.toNamed() 命名路由跳转
Get.back() 路由返回
Get.off() 进入下一个页面,但没有返回上一个页面的选项(用于闪屏页,登录页面等)
Get.offAll() 进入下一个页面并取消之前的所有路由
Get.offAndToNamed() 跳转并使用下一个路由替换当前路由页面(可用于关闭中间页面,如搜索页面)
Get.removeRoute() 删除一个路由
Get.until() 反复返回,直到表达式返回真
Get.offUntil() 转到下一条路由,并删除所有之前的路由,直到表达式返回true
Get.offNamedUntil() 转到下一个命名的路由,并删除所有之前的路由,直到表达式返回true
Get.arguments 获取当前路由页面的参数
Get.previousRoute 获取之前的路由名称
Get.rawRoute 给出要访问的原始路由

Ok, 这些只是一部分,你可以到官方网站查看更多详细的用法,下面说下具体的使用。

先看下综合示例效果图,程序下载(Git 下载地址):

Flutter_get_C.gif


二、普通路由导航

2.1 示例

(1)设置应用程序入口

当我们导入依赖后,在应用程序顶层把 GetMaterialApp 作为顶层,如下所示:

import 'package:flutter/material.dart';
import 'package:get/get.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp( // 修改为GetMaterialApp
      title: "GetX",
      home: Scaffold(
        appBar: AppBar(
          title: const Text("GetX Title"),
        ),
        body: const MyHomePage(),
      ),
    );
  }
}

MyHomePage 类在后面实现。


(2)创建一个新的页面文件

然后,在lib目录下创建一个名为nextScreenPage.dart的文件:

import 'package:flutter/material.dart';
import 'package:get/get.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: Center(
        child: ElevatedButton(
            onPressed: () {
              Get.back(); // 返回到前一页
            },
            child: const Text("返回上一个页面")),
      ),
    );
  }
}

同时,使用了Get.back()方法,按下按钮可以返回到前一页,一般都与Get.to()一起使用。


(3)调用to方法切换路由

import 'package:custom/nextScreenPage.dart';

ElevatedButton(
	onPressed: () async {
	Get.to(const NextScreenPage()); // to方法实现页面跳转
},
child: const Text("普通路由跳转")),

包含这个按钮的完整 MyHomePage 类实现如下:

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          ElevatedButton(
              onPressed: () async {
                Get.to(const NextScreenPage()); // to方法实现页面跳转
              },
              child: const Text("普通路由跳转")),
        ],
      ),
    );
  }
}

使用了Get.to()方法,按下按钮可以调整到指定的页面。


2.2 GetX用法与原生路由的对比

(1)打开到新的页面:

Get.to(NextScreen());

对应原生路由:

Navigator.push(context, MaterialPageRoute<void>(
  builder: (BuildContext context) {
    return NextScreen();
  },
));

(2)返回:

Get.back();

对应原生路由:

Navigator.pop(context);

(3)打开新页面,并且用新页面替换旧页面(删除旧页面):

Get.off(NextScreen());

对应原生路由:

 Navigator.pushReplacement(context, MaterialPageRoute<void>(
      builder: (BuildContext context) {
        return NextScreen();
      },
    ));

(4)打开新页面并删除之前的所有路由:

Get.offAll(NextScreen());

对应原生路由:

Navigator.pushAndRemoveUntil(
  context,
  MaterialPageRoute<void>(
    builder: (BuildContext context) {
      return NextScreen();
    },
  ),
  (Route<dynamic> route) => false,
);

(5)导航到新页面,在返回时接收返回数据:

var data = await Get.to(NextScreen());

对应原生路由:

var data = await  Navigator.push(context, MaterialPageRoute<void>(
  builder: (BuildContext context) {
    return NextScreen();
  },
));

(6)带返回值返回前一个路由,配合上面使用:

Get.back(result: 'success');

对应原生路由:

 Navigator.pop(context, 'success');

三、别名路由导航

3.1 别名路由定义

(1)声明别名:

abstract class Routes {
  static const Home = '/';
  static const NextScreen = '/NextScreen';
}

(2)注册路由表:

abstract class AppPages {
  static final pages = [
    GetPage(
      name: Routes.Home,
      page: () => const MyHomePage(),
    ),
    GetPage(
      name: Routes.NextScreen,
      page: () => const NextScreenPage(),
    ),
  ];
}

(3)替换MaterialApp为GetMaterialApp:

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: "GetX",
      home: Scaffold(
        appBar: AppBar(
          title: const Text("GetX Title"),
        ),
        body: const MyHomePage(),
      ),
    );
  }
}

3.2 示例

假如我们有一个 NextScreenPage 页面,使用别名路由的时候,上面示例中 MyApp 类修改如下:

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: "GetX",
      home: Scaffold(
        appBar: AppBar(
          title: const Text("GetX Title"),
        ),
        body: const MyHomePage(),
      ),
      // 主页面路由
      initialRoute: Routes.Home,
      // 注册路由表
      getPages: AppPages.pages,
    );
  }
}

然后调用Get.toNamed()跳转到命名路由,上面示例中的 MyHomePage 类修改如下:

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
					//......
          // 别名路由跳转
          ElevatedButton(
              onPressed: () async {
                Get.toNamed(Routes.NextScreen); // toNamed方法实现页面跳转
              },
              child: const Text("别名路由跳转")),
        ],
      ),
    );
  }
}

3.3 GetX用法与原生路由的对比

(1)导航到下一个页面:

Get.toNamed(Routes.NextScreen);

(2)导航到下一个页面并删除前一个页面:

Get.offNamed(Routes.NextScreen);

(3)导航到下一个页面并删除以前所有的页面:

Get.offAllNamed(Routes.NextScreen);

四、别名路由传值

通过 argument 传递参数,argument 接收字符串、Map、List、类的实例。

获取参数:

String name=Get.arguments;

4.1 创建一个新的页面文件

新建 valueTransferPage.dart 文件,作为接收页面,内容如下:

import 'package:flutter/material.dart';
import 'package:get/get.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text("别名路由传值页面"),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(Get.arguments), // 别名路由传值,在这里接收
          ElevatedButton(
              onPressed: () {
                Get.back();
              },
              child: const Text("返回上一个页面")),
        ],
      ),
    );
  }
}

4.2 通过 argument 传递参数

主页面修改如下:

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:custom/next_screen_page.dart';
import 'package:custom/value_transfer_page.dart';

void main() {
  runApp(const MyApp());
}

// 声明别名
abstract class Routes {
  static const Home = '/';
  static const NextScreen = '/NextScreen';
  static const ValueTransfer = '/ValueTransfer';
}

// 注册路由表
abstract class AppPages {
  static final pages = [
    GetPage(
      name: Routes.Home,
      page: () => const MyHomePage(),
    ),
    GetPage(
      name: Routes.NextScreen,
      page: () => const NextScreenPage(),
    ),
    GetPage(
      name: Routes.ValueTransfer,
      page: () => const ValueTransferPage(),
    ),
  ];
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: "GetX",
      home: Scaffold(
        appBar: AppBar(
          title: const Text("GetX Title"),
        ),
        body: const MyHomePage(),
      ),
      // 主页面路由
      initialRoute: Routes.Home,
      // 注册路由表
      getPages: AppPages.pages,
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          // 普通路由跳转
          ElevatedButton(
              onPressed: () async {
                Get.to(const NextScreenPage()); // to方法实现页面跳转
              },
              child: const Text("普通路由跳转")),
          // 别名路由跳转
          ElevatedButton(
              onPressed: () async {
                Get.toNamed(Routes.NextScreen); // toNamed方法实现页面跳转
              },
              child: const Text("别名路由跳转")),
          // 别名路由传值跳转
          ElevatedButton(
              onPressed: () async {
                Get.toNamed(Routes.ValueTransfer,
                    arguments: "别名路由传值页面"); // toNamed方法带参数实现页面跳转
              },
              child: const Text("别名路由传值跳转")),
        ],
      ),
    );
  }
}

五、配置动画

defaultTransition 可以配置默认动画,修改上面示例如下:

// 注册路由表
abstract class AppPages {
  static final pages = [
    GetPage(
      name: Routes.Home,
      page: () => const MyHomePage(),
    ),
    GetPage(
      name: Routes.NextScreen,
      page: () => const NextScreenPage(),
      transition: Transition.rightToLeft, // 页面跳转动画
    ),
    GetPage(
      name: Routes.ValueTransfer,
      page: () => const ValueTransferPage(),
      transition: Transition.rightToLeft, // 页面跳转动画
    ),    
  ];
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: "GetX",
      home: Scaffold(
        appBar: AppBar(
          title: const Text("GetX Title"),
        ),
        body: const MyHomePage(),
      ),
      defaultTransition: Transition.rightToLeftWithFade, // 配置默认动画
      // 主页面路由
      initialRoute: Routes.Home,
      // 注册路由表
      getPages: AppPages.pages,
    );
  }
}

六、路由抽离

当页面数目很多时,可以新建 routes.dart,将别名路由定义放在这个文件中:

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:custom/nextScreenPage.dart';
import 'package:custom/valueTransferPage.dart';

// 声明别名
abstract class Routes {
  static const Home = '/';
  static const NextScreen = '/NextScreen';
  static const ValueTransfer = '/ValueTransfer';
}

// 注册路由表
abstract class AppPages {
  static final pages = [
    GetPage(
      name: Routes.Home,
      page: () => const MyHomePage(),
    ),
    GetPage(
      name: Routes.NextScreen,
      page: () => const NextScreenPage(),
      //transition: Transition.rightToLeft, // 页面跳转动画
    ),
    GetPage(
      name: Routes.ValueTransfer,
      page: () => const ValueTransferPage(),
      //transition: Transition.rightToLeft, // 页面跳转动画
    ),    
  ];
}

项目结构图如下:

Flutter_Get_H.png


参考:

Flutter状态管理终极方案GetX第一篇——路由 - 简书 (jianshu.com)

Flutter Getx 路由管理 - 鲤斌 - 博客园 (cnblogs.com)

Flutter中GetX的用法(超详细使用指南之路由管理篇)_flutter getx-CSDN博客


posted @ 2024-10-18 10:10  fengMisaka  阅读(88)  评论(0编辑  收藏  举报