• Flutter:getX的学习


    前言

    学习教程Getx教程_Flutter+Getx系列实战教程

    简介
    getX是第三方的状态管理插件,不仅具有状态管理的功能,还具有路由管理、主题管理、国际化多语言管理、网络请求、数据验证等功能。相比其他状态管理组件,getX简单、功能强大。

    官方文档
    https://pub-web.flutter-io.cn/packages/get

    安装

    flutter pub add get
    
    • 1

    MaterialApp修改为GetMaterialApp

    GetMaterialApp(
          title: 'getx',
          theme: ThemeData(
            colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
            useMaterial3: true,
          ),
          home: const MyHomePage(title: 'getx'),
        );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    Dialog、snackbar、bottomSheet

    Dialog

    ElevatedButton(
               onPressed: () {
                 Get.defaultDialog(
                     title: "默认弹窗",
                     middleText: '弹出内容,你确定要卸载吗?',
                     confirm:
                         TextButton(onPressed: () {
                           Get.back();
                         }, child: const Text("确定")),
                     cancel:
                         TextButton(onPressed: () {
                           Get.back();
                         }, child: const Text("取消")));
               },
               child: const Text("getx 默认dialog"))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    snackbar

    ElevatedButton(
        onPressed: () {
          Get.snackbar("提示", "删除成功");
        },
        child: const Text("snack-bar"))
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    bottomSheet

    ElevatedButton(
       onPressed: () {
         Get.bottomSheet(Container(
           color: Colors.white,
           height: 130,
           child: Column(
             children: [
               ListTile(
                 leading: const Icon(Icons.wb_sunny_outlined),
                 title: const Text("白天模式"),
                 onTap: () {
                   Get.changeTheme(ThemeData.light());
                     Get.back();
                 },
               ),
               const Divider(),
               ListTile(
                 leading: const Icon(Icons.wb_sunny),
                 title: const Text("夜间模式"),
                 onTap: () {
                   Get.changeTheme(ThemeData.dark());
                     Get.back();
                 },
               ),
             ],
           ),
         ));
       },
       child: const Text("snack-bar"))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在这里插入图片描述

    路由管理

    GetX 为我们封装了Navigation,无需context可进行跳转。使用GetX进行路由跳转更加的简单。只需要使用Get.to() 可进行路由跳转,GetX对路由跳转简化了跳转动画设置、动画时长定义、动画曲线设置

    我们可以通过Get.to()实现普通的路由跳转,通过Get.toNamed实现命名路由跳转,通过Get.back()实现返回上一级路由,通过Get.ofAll()返回跟路由,可以通过Get.off()将当前页面从页面栈中移除,并将新的页面添加到页面栈中,可以通过Get.arguments获取到路由传参

    配置路由及路由动画

    GetMaterialApp(
          title: 'getx',
          theme: ThemeData(
            colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
            useMaterial3: true,
          ),
          // home 和 initialRoute同时存在的话initialRoute会优先生效
          home: const MyHomePage(title: 'getx'), // 主页
          initialRoute: '/', // 默认显示的路由页面
          defaultTransition: Transition.leftToRight, // 设置所有页面默认的路由跳转动画
          getPages: [
            //路由地址
            GetPage(name: '/', page: () => const MyHomePage(title: 'getx')),
            GetPage(
                name: '/my',
                page: () => const MyInfo(),
                transition: Transition.leftToRight // 设置路由过度动画
                )
          ],
        )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
     Get.toNamed('my', arguments: {"message": 'Hello Flutter'});
    
    • 1
      Widget build(BuildContext context) {
        String mes = Get.arguments?["message"] ?? '11';
        return Scaffold(
          appBar: AppBar(
            title: const Text('我的'),
          ),
          body: Center(
            child: Text("个人信息:$mes"),
          ),
        );
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    路由抽离

    import 'package:test/page/my.dart';
    import 'package:get/get.dart';
    
    class AppPage {
      static final List<GetPage<dynamic>> routes = [
        GetPage(
            name: '/my',
            page: () => const MyInfo(),
            transition: Transition.leftToRight // 设置路由过度动画
            )
      ];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    GetMaterialApp(
          title: 'getx',
          theme: ThemeData(
            colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
            useMaterial3: true,
          ),
          // home 和 initialRoute同时存在的话initialRoute会优先生效
          home: const MyHomePage(title: 'getx'), // 主页// 默认显示的路由页面
          defaultTransition: Transition.leftToRight, // 设置所有页面默认的路由跳转动画
          getPages: AppPage.routes,
        )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    路由中间件(路由守卫)

    import 'package:flutter/cupertino.dart';
    import 'package:test/page/my.dart';
    import 'package:get/get.dart';
    
    class AppPage {
      static final List<GetPage<dynamic>> routes = [
        GetPage(
            name: '/my',
            page: () => const MyInfo(),
            transition: Transition.leftToRight, // 设置路由过度动画
            middlewares: [MyMiddleWare()])
      ];
    }
    
    // 中间件
    class MyMiddleWare extends GetMiddleware {
      // 重写重定向
      
      redirect(route) {
        String power = Get.arguments?['power'];
        if (power == 'no') {
          Get.snackbar("提示", "请先进行登录");
          return const RouteSettings(name: 'login');
        }
        // 放行,跳转到目标路由
        return null;
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    状态管理

    主要用与多个页面共享状态使用,某一个页面的状态改变,其他页面也随着改变。

    单页面状态管理

    class _MyHomePageState extends State<MyHomePage> {
      // 定义一个响应式的整数
      RxInt count = 0.obs;
      // 或者
      RxInt a = RxInt(0);
    
      
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            backgroundColor: Theme.of(context).colorScheme.inversePrimary,
            title: Text(widget.title),
          ),
          // const Color(0x00cab6ec)
          body: Column(
            children: [
              ElevatedButton(
                  onPressed: () {
                    count.value += 1;
                  },
                  child: const Text("加1")),
              //   监听值的变化
               Obx(() => Text("当前值:${count.value}"))
            ],
          ),
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    如果使用过vue3,那么接受起来就非常容易了。

    优点:如果使用setState 会重新运行build进行更新,如果内容过多的话,会产生较大的开销。使用Getx只会更新你监听的组件,实现一个局部更新。

    多页面状态管理

    定义一个Controller

    import 'package:get/get.dart';
    
    class CountController extends GetxController {
      // 定义响应式变量
      RxInt count = 0.obs;
    //  增加
      void add() {
        count.value++;
        // 调用GetxController内置方法进行更新
        update();
      }
    
    // 减少
      void del() {
        count.value--;
        // 调用GetxController内置方法进行更新
        update();
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    主页面使用

    class _MyHomePageState extends State<MyHomePage> {
      // 创建控制器示例
      CountController countController =
          Get.put(CountController(), tag: 'countController');
    
      
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            backgroundColor: Theme.of(context).colorScheme.inversePrimary,
            title: Text(widget.title),
          ),
          // const Color(0x00cab6ec)
          body: Column(
            children: [
              ElevatedButton(
                  onPressed: () {
                    Get.toNamed('/my');
                  },
                  child: const Text("我的")),
              ElevatedButton(
                  onPressed: () {
                    // 加1
                    countController.add();
                  },
                  child: const Text("加1")),
              //   监听值的变化
              Obx(() => Text("当前值:${countController.count.value}"))
            ],
          ),
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    其他页面使用

    class MyInfoState extends State<MyInfo> {
      // 获取示例
      late final CountController countController;
    
      
      void initState() {
        super.initState();
        countController = Get.find(tag: 'countController');
      }
    
      
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('我的'),
          ),
          body: Center(
            child: ElevatedButton(
              child: const Text("减1"),
              onPressed: () {
                countController.del();
              },
            ),
          ),
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    在这里插入图片描述

    全局监听路由

    控制器

    /// 用于记录路由的变化
    class RouteChangeController extends GetxController {
      // 路由地址
      RxString currentRoute = ''.obs;
      // 修改路由地址
      editCurrentRoute(String? route) {
        currentRoute.value = route ?? '';
        print("路由地址是:${currentRoute.value}");
        //更新状态
        update();
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    设置路由监听,当路由事件触发时,调用routingCallback回调

     // 获取路由控制器
     RouteChangeController routeChangeController =
            Get.put(RouteChangeController(), tag: 'ScreenSizeController');
    
    GetMaterialApp(
        ....
        // 监听路由变化
        routingCallback: (routing) {
          debugPrint("路由变化了:${routing?.current}");
          // 记录路由
          routeChangeController.editCurrentRoute(routing?.current);
        },
      );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在需要使用的页面里进行监听

    
    void initState() {
      super.initState();
      // 监听路由的变化
      routeChangeController.currentRoute.listen((value) {
        // 刷新小说列表
        print("路由发生了变化,值是:${value}");
      });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    GetX Binding

    在我们所有使用Getx状态管理器时,都需要手动创建一个示例,这样是是否麻烦的。而使用Binding可以在项目初始化时把需要使用的状态管理器统一进行初始化。

    创建示例的几个方法

    • Get.put,不使用控制器实例也会被创建
    • Get.lazyPut,懒加载方式创建实例,只有在使用时才会被创建
    • Get.putAsyncGet.put的异步版本
    • Get.create,每次使用都会创建一个新的实例

    创建绑定类

    import 'package:get/get.dart';
    
    import 'count_controller.dart';
    
    class AllControllerBinding implements Bindings {
      
      void dependencies() {
        // 初始化
        Get.lazyPut<CountController>(() => CountController());
        // 多个则多执行几次Get.lazyPut
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在main.dart中初始化

    GetMaterialApp(
          title: 'getx',
          // 初始化绑定状态管理类
          initialBinding: AllControllerBinding(),
          theme: ThemeData(
            colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
            useMaterial3: true,
          ),
          // home 和 initialRoute同时存在的话initialRoute会优先生效
          home: const MyHomePage(title: 'getx'), // 主页// 默认显示的路由页面
          defaultTransition: Transition.leftToRight, // 设置所有页面默认的路由跳转动画
          getPages: AppPage.routes,
        )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    使用
    初始化完成后,就不需要再进行创建。使用时只需要通过Get.find来获取实例即可

    CountController  countController = Get.find<CountController>();
    
    • 1

    GetView

    GetViewGetX框架中的一个重要组件,它主要用于简化页面组件的创建和管理。通过继承GetView,可以方便地创建一个具有状态管理和路由导航功能的页面。

    GetView的作用主要有以下几点:

    • 简化页面的创建:继承GetView后,只需重写Widget build(BuildContext context)方法即可创建页面,无需再手动创建StatefulWidgetStatelessWidget

    • 管理页面状态:GetView内部封装了GetX框架提供的状态管理功能,可以轻松实现状态的监听、更新和销毁,避免了手动管理状态的繁琐操作。

    • 路由导航:GetView提供了简单的路由导航功能,可以通过Get.to()Get.off()等方法进行页面跳转,并且可以携带参数传递。

    • 依赖注入:GetView内置了依赖注入功能,可以通过Get.put()Get.lazyPut()等方法来注册和获取全局的依赖对象,方便在页面中使用。

    总的来说,GetView的作用是简化页面组件的创建和管理,提供了便捷的状态管理和路由导航功能,使得开发者可以更专注于业务逻辑的实现。

    实例

    // 需要指定要使用的状态管理类
    class MyInfoPage extends GetView<CountController> {
      const MyInfoPage({super.key});
    
      
      Widget build(BuildContext context) {
        // 如果第一次使用还需要put(没有结合Binding时)
        Get.put(CountController());
        return Scaffold(
          appBar: AppBar(
            title: const Text('我的'),
          ),
          body: Center(
            child: ElevatedButton(
              child: const Text("减1"),
              onPressed: () {
                // 因为几次了GetView并且指定了泛型,因此可以获取到对应controller
                controller.del();
              },
            ),
          ),
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    几种使用情况:

    • 只是单纯展示共享状态或者需要对共享状态操作
    • 既有共享状态又有私有状态,这是可以结合响应式状态变量来使用。这样就不需要创建StatefulWidget以及其对应的State

    多语言配置

    略,可以自行观看视频。

    工具类——GetUtils

    GetUtilsGetx提供的工具类库,包含值是否为空、是否是数字、视频、音频、ppt、邮箱、手机号等。

  • 相关阅读:
    portraiture中文版下载切换教程v3.5.6版本
    Fabric v2.5区块链应用开发实战大纲
    浏览器视频倍速播放方法
    Android native层实现MediaCodec编码H264/HEVC
    并发编程——1.java内存图及相关内容
    【Flask框架】四. Flask框架之 MySQL数据库操作及项目重构
    【教3妹学编程-算法题】最长奇偶子数组
    CAD插入文件,使文件不跟随源对象而改变
    APP攻防--安卓逆向&JEB动态调试&LSPosed模块&算法提取&Hook技术
    你知道STM32和51单片机的区别吗?
  • 原文地址:https://blog.csdn.net/weixin_41897680/article/details/132258062