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工程的时候,系统会生成一个计时器的示例代码,代码大致如下(我删除了部分注释代码):

Dart 复制代码
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

主要功能是点击+按钮,每次计时器的个数+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,节省下内存。修改之后的完整代码如下:

Dart 复制代码
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(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
class Controller extends GetxController{
  var counter = 0.obs;
  incrementCounter()=>counter++;
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  Widget build(BuildContext context) {
    final Controller controller = Get.put(Controller());

    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Obx(() => Text(
              '${controller.counter}',
              style: Theme.of(context).textTheme.headlineMedium,
            )),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: (){
          controller.incrementCounter();
        },
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

三.Getx路由管理

1.普通路由导航

1.导航到新的页面

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

Dart 复制代码
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.
    );
  }
}

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

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

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

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

Get.back();

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("返回上一个页面")),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}
3.进入下一个页面,但没有返回上一个页面的选项(用于SplashScreens,登录页面等)

主要的代码如下:

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

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

登陆页面代码如下:

Dart 复制代码
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:getx_demos/route_manager/login/profile_page.dart';

class LoginPage extends StatelessWidget {
  const LoginPage({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.to(()=>const ProfilePage());
        }, child: const Text("点击进入个人中心页面")),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

个人中心页面代码如下:

Dart 复制代码
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:getx_demos/route_manager/normal_route_page.dart';

class ProfilePage extends StatelessWidget {
  const ProfilePage({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.off(const NormalRoutePage(title: "主页面"));
        }, child: const Text("返回主页面")),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}
4.进入下一个界面并取消之前的所有路由

Get.offAll(NextScreen());

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

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

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

SecondPage页面代码如下:

Dart 复制代码
import 'package:getx_demos/route_manager/login/third_page.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text("回调传值"),
      ),
      body: Column(
        children: [
          Center(
            child: ElevatedButton(onPressed: () async {
              var data = await Get.to(const ThirdPage());
              debugPrint("下个页面回调值:$data");
              Get.to(()=>const ThirdPage());
            }, child: const Text("跳转Third页面")),
          ),
        ],
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

ThirdPage页面代码如下:

Dart 复制代码
import 'package:flutter/material.dart';
import 'package:get/get.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text("Third"),
      ),
      body: Column(
        children: [
          const Text("第二个页面传过来的值:"),
          Center(
            child: ElevatedButton(onPressed: (){
              Get.back(result: "555555");
            }, child: const Text("返回主页面")),
          ),
        ],
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

2.别名路由导航

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

Dart 复制代码
class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Flutter Demo',
      initialRoute: "/",
      getPages: [
        GetPage(name: "/next_screen", page: ()=>const NextScreenPage()),
      ],
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
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:

Dart 复制代码
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: () {},
),
],
)
);

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地址。

相关推荐
Georgewu9 天前
【HarmonyOS 5】鸿蒙跨平台开发方案详解(一)
flutter·harmonyos
爱吃鱼的锅包肉9 天前
Flutter开发中记录一个非常好用的图片缓存清理的插件
flutter
张风捷特烈10 天前
每日一题 Flutter#13 | build 回调的 BuildContext 是什么
android·flutter·面试
恋猫de小郭10 天前
Flutter 又双叒叕可以在 iOS 26 的真机上 hotload 运行了,来看看又是什么黑科技
android·前端·flutter
QC七哥10 天前
跨平台开发flutter初体验
android·flutter·安卓·桌面开发
小喷友10 天前
Flutter 从入门到精通(水)
前端·flutter·app
恋猫de小郭10 天前
Flutter 里的像素对齐问题,深入理解为什么界面有时候会出现诡异的细线?
android·前端·flutter
tbit11 天前
dart私有命名构造函数的作用与使用场景
flutter·dart
法的空间11 天前
JsonToDart,你已经是一个成熟的工具了,接下来就靠你自己继续进化了!
android·flutter·ios