当前位置: 首页 > news >正文

flutter getx路由管理、状态管理、路由守卫中间件、永久储存get_storage

一个简单的路由跳转、状态管理

目录

lib/
├── main.dart
├── routes/index.dart         // 路由表
├── middlewares/auth_middleware.dart  // 登录守卫
├── pages/
│   ├── home_page.dart
│   ├── login_page.dart
│   └── profile_page.dart
└── controllers/auth_controller.dart  // 登录状态管理

✅ 1. 登录状态控制器(AuthController)

// controllers/auth_controller.dart
import 'package:get/get.dart';class AuthController extends GetxController {var isLoggedIn = false.obs;void login() => isLoggedIn.value = true;void logout() => isLoggedIn.value = false;
}

✅ 2. 路由守卫中间件(AuthMiddleware)

// middlewares/auth_middleware.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/auth_controller.dart';class AuthMiddleware extends GetMiddleware {@overrideRouteSettings? redirect(String? route) {final auth = Get.find<AuthController>();if (!auth.isLoggedIn.value) {return const RouteSettings(name: '/login');}return null; // 正常访问}@overrideint? priority = 0; // 优先级
}

✅ 3. 页面:Home、Login、Profile

// pages/home_page.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/auth_controller.dart';class HomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {final auth = Get.find<AuthController>();return Scaffold(appBar: AppBar(title: const Text("首页")),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [const Text("欢迎来到首页"),ElevatedButton(onPressed: () => Get.toNamed("/profile"),child: const Text("进入个人中心"),),ElevatedButton(onPressed: auth.logout,child: const Text("退出登录"),)],),),);}
}
// pages/login_page.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/auth_controller.dart';class LoginPage extends StatelessWidget {@overrideWidget build(BuildContext context) {final auth = Get.find<AuthController>();return Scaffold(appBar: AppBar(title: const Text("登录页")),body: Center(child: ElevatedButton(onPressed: () {auth.login();Get.offAllNamed('/home');},child: const Text("点击登录"),),),);}
}
// pages/profile_page.dart
import 'package:flutter/material.dart';class ProfilePage extends StatelessWidget {@overrideWidget build(BuildContext context) {return const Scaffold(body: Center(child: Text("这是个人中心")),);}
}

✅ 4. 路由定义(routes.dart)

// routes.dart
import 'package:get/get.dart';
import 'middlewares/auth_middleware.dart';
import 'pages/home_page.dart';
import 'pages/login_page.dart';
import 'pages/profile_page.dart';final List<GetPage> appRoutes = [GetPage(name: '/login', page: () => LoginPage()),// 添加守卫的页面GetPage(name: '/home',page: () => HomePage(),middlewares: [AuthMiddleware()],),GetPage(name: '/profile',page: () => ProfilePage(),middlewares: [AuthMiddleware()],),
];

✅ 5. 启动文件(main.dart)

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'controllers/auth_controller.dart';
import 'routes.dart';void main() {Get.put(AuthController()); // 注册控制器runApp(MyApp());
}class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return GetMaterialApp(debugShowCheckedModeBanner: false,initialRoute: '/home',getPages: appRoutes,);}
}

重点

  • Get.find(); 在 main() 中全局注册
  • 路由配置中需要添加 中间件

Getx 路由套转配置方式

方法功能示例
Get.to()普通跳转Get.to(DetailPage())
Get.toNamed()跳转到命名路由Get.toNamed('/home')
Get.back()返回上一页Get.back()
Get.off()替换当前页面Get.off(DetailPage())
Get.offNamed()替换并跳转命名路由Get.offNamed('/home')
Get.offAll()清除所有页面,跳转Get.offAll(MainPage())
Get.offAllNamed()清除所有页面并跳转命名路由Get.offAllNamed('/login')
Get.toNamed('/page', arguments: data)传递数据接收:Get.arguments
Get.toNamed('/page/123')传递路径参数Get.parameters['id']

✅ 二、路由配置:GetMaterialApp + getPages

void main() {runApp(MyApp());
}class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return GetMaterialApp(title: 'GetX Demo',initialRoute: '/',getPages: [GetPage(name: '/', page: () => HomePage()),GetPage(name: '/login', page: () => LoginPage()),GetPage(name: '/detail/:id', page: () => DetailPage()),],);}
}

✅ 三、参数传递方式

传递 arguments(类似 Vue 的 query)
// 跳转时传
Get.toNamed('/detail', arguments: {'title': 'GetX 超棒!'});// 接收
final args = Get.arguments;
2️⃣ 传递 path 参数(像 /user/123)
// 定义路由
GetPage(name: '/user/:id', page: () => UserPage());// 跳转
Get.toNamed('/user/123');// 接收参数
final id = Get.parameters['id']; // 获取的是 '123'

✅ 四、嵌套路由(子路由)

GetPage(name: '/parent',page: () => ParentPage(),children: [GetPage(name: '/child', page: () => ChildPage()),],
);

跳转方式:

Get.toNamed('/parent/child');

✅ 五、使用中间件(路由守卫)

GetPage(name: '/home',page: () => HomePage(),middlewares: [AuthMiddleware()],
);
  • 中间件例子:
class AuthMiddleware extends GetMiddleware {@overrideRouteSettings? redirect(String? route) {final auth = Get.find<AuthController>();if (!auth.isLoggedIn.value) {return const RouteSettings(name: '/login');}return null;}
}

✅ 六、转场动画

GetPage(name: '/about',page: () => AboutPage(),transition: Transition.rightToLeft,transitionDuration: const Duration(milliseconds: 300),
);

七、导航栏方式(bottomNavigation + 路由)

  • 你也可以结合 GetX + IndexedStack 做底部导航 + 路由组合(需要时我可以提供完整例子)。

✅ 跳转方法速查表:

方法作用
Get.to(Widget)Push 一个页面
Get.off(Widget)替换当前页面
Get.offAll(Widget)清除所有页面
Get.toNamed('/path')跳转命名路由
Get.offNamed('/path')替换当前为命名路由
Get.offAllNamed('/path')全部清除并跳转命名
Get.back()返回上一级
Get.arguments获取传递的对象
Get.parameters获取 path 中的参数(如 /user/:id)

Getx 状态管理

  1. 响应式变量基础(Rx 类型)
  2. GetX 控制器结构与绑定
  3. UI 自动刷新更新机制
  4. GetStorage 实现永久存储
  5. 增删改查完整示例
  6. 完整状态管理架构建议

响应式变量基础(Rx 类型)

类型示例使用说明
RxIntRxInt count = 0.obs;obs 创建响应式变量
RxStringvar name = ''.obs;自动追踪变化
RxListRxList items = [].obs;响应式数组
RxMapRxMap map = {}.obs;响应式字典
Rx<T>Rx<User> user = User().obs;自定义类型
改变值方式:
count.value++;
name.value = '新名称';
items.add('新项');
map['key'] = 'value';

2️⃣ GetX 控制器结构与绑定

class CounterController extends GetxController {var count = 0.obs;void increment() {count.value++;}
}
  • 注册控制器:
// main.dart
Get.put(CounterController());
// 页面中局部绑定
final counter = Get.put(CounterController());

3️⃣ UI 自动刷新更新机制

  1. 方法 1:Obx(最推荐)
Obx(() => Text('计数:${counter.count}'));
  1. 方法 2:GetX Widget
GetX<CounterController>(builder: (controller) => Text('${controller.count}'),
);
  1. 方法 3:GetBuilder(非响应式,只手动更新)
GetBuilder<CounterController>(builder: (_) => Text('${_.count}'),
);

GetBuilder 适用于不频繁更新的组件,需要手动调用 update()。

4️⃣ GetStorage 实现永久存储(本地缓存)

步骤 1:引入依赖
dependencies:get_storage: ^2.1.1
步骤 2:初始化
void main() async {await GetStorage.init(); // 必须 await 初始化runApp(MyApp());
}
步骤 3:使用
final box = GetStorage();// 存
box.write('isLoggedIn', true);// 取
bool isLoggedIn = box.read('isLoggedIn') ?? false;// 删
box.remove('isLoggedIn');

5️⃣ 增删改查完整示例(以 RxList 为例)

class TodoController extends GetxController {var todos = <String>[].obs;void add(String task) => todos.add(task);void updateAt(int index, String newValue) => todos[index] = newValue;void delete(int index) => todos.removeAt(index);void clear() => todos.clear();
}
  • 使用:
final todoController = Get.find<TodoController>();Obx(() => ListView.builder(itemCount: todoController.todos.length,itemBuilder: (_, i) => ListTile(title: Text(todoController.todos[i]),trailing: IconButton(icon: Icon(Icons.delete),onPressed: () => todoController.delete(i),),),
));

6️⃣ 完整状态管理架构建议

功能推荐方式
页面数据共享使用 Get.put() 全局注册控制器
子页面控制器Get.lazyPut() 按需注册
多状态切换用多个 RxBool / RxEnum 控制
页面重构控制器 + Obx 封装成组件
状态持久化GetStorage 存取数据
中间件判断状态Get.find<Controller>().xxx.value

✅ 示例:登录状态持久化控制器(完整)

class AuthController extends GetxController {final storage = GetStorage();var isLoggedIn = false.obs;@overridevoid onInit() {super.onInit();isLoggedIn.value = storage.read('isLoggedIn') ?? false;}void login() {isLoggedIn.value = true;storage.write('isLoggedIn', true);}void logout() {isLoggedIn.value = false;storage.remove('isLoggedIn');}
}

状态管理,永久存储 get_storage

  1. 在pubspec.yaml文件中添加库的依赖:
dependencies:get_storage: ^2.1.1
  1. 然后运行:
flutter pub get

✅ 2. 初始化(必须)

  • 在 main.dart 的入口函数中初始化:
import 'package:get_storage/get_storage.dart';void main() async {await GetStorage.init(); // 初始化存储runApp(MyApp());
}

注意:await GetStorage.init() 是异步方法,必须在 runApp() 前执行。

✅ 3. 基本用法

final box = GetStorage(); // 实例化,默认使用 'GetStorage' 区域// 写入数据
box.write('username', '张三');// 读取数据
String name = box.read('username') ?? '游客';// 删除某个值
box.remove('username');// 清空所有数据
box.erase();// 判断是否存在
bool exists = box.hasData('username');

✅ 4. 支持的类型

支持所有基本类型和 Map、List:

类型示例
String'张三'
int100
double3.14
booltrue
List<String>['a', 'b']
Map<String, dynamic>{'id': 1, 'name': 'Tom'}

✅ 5. 多区域存储(类似命名空间)

  • 你可以为不同模块使用不同的存储文件(如用户模块/缓存模块)
await GetStorage.init('user');
final userBox = GetStorage('user');userBox.write('token', '123456');
print(userBox.read('token'));

✅ 6. 实时监听值变化(响应式)

box.listen(() {print('本地数据发生变化');
});
  • 你也可以监听某个 key:
box.listenKey('isDark', (value) {print('主题设置变为:$value');
});

✅ 7. 搭配 GetX Controller 使用(推荐)

  • 例如保存登录状态:
class AuthController extends GetxController {final storage = GetStorage();var isLoggedIn = false.obs;@overridevoid onInit() {super.onInit();isLoggedIn.value = storage.read('isLoggedIn') ?? false;}void login() {isLoggedIn.value = true;storage.write('isLoggedIn', true);}void logout() {isLoggedIn.value = false;storage.remove('isLoggedIn');}
}

✅ 8. 存储对象(推荐使用 JSON)

final user = {'id': 1,'name': 'Alice','roles': ['admin', 'editor'],
};box.write('user', user);// 读取
Map userData = box.read('user');

如需存储自定义对象,请使用 toJson / fromJson 显式转换。

✅ 9. 总结速查表

操作方法示例
初始化await GetStorage.init()在 main() 中
实例化GetStorage()可传命名空间
写入.write('key', value)
读取.read('key')
删除.remove('key')
清空.erase()
判断.hasData('key')
监听所有.listen((){})
监听某项.listenKey('key', callback)

使用场景推荐

场景建议用法
登录状态bool 持久化 + 控制器绑定
用户信息Map 存储 JSON
主题模式bool 监听并更新 UI
App 首次启动设置 isFirstRun 标志位
临时缓存数据write + remove 清理机制
http://www.xdnf.cn/news/588925.html

相关文章:

  • 汇川EasyPLC MODBUS-RTU通信配置和编程实现
  • S7-1500PLC通过工艺对象实现V90总线伺服定位控制(105报文)
  • 英伟达有意入股 PsiQuantum,释放战略转向量子计算的重要信号
  • JVM常量池(class文件常量池,运行时常量池,字符串常量池)
  • Mysql数据库之索引与事务
  • 【内部教程】ISOLAR-AB配置以太网栈|超详细实战版
  • Kotlin与Flutter:跨平台开发的互补之道与实战指南
  • Armadillo C++ 线性代数库介绍与使用
  • Kotlin 极简小抄 P10(类与对象、主构造函数、带有默认参数值的主构造函数、次要构造函数)
  • 【机器学习】集成学习算法及实现过程
  • Ubuntu20.04的安装(VMware)
  • 详解受约束的强化学习(四、数学符号说明)
  • PL/Python数据库: PostgreSQL Python扩展
  • Argo CD 详解:从 GitOps 到持续交付的完整实践
  • 关于数据仓库、数据湖、数据平台、数据中台和湖仓一体的概念和区别
  • 相机标定与图像处理涉及的核心坐标系
  • 2. PyQGIS Windows下开发环境搭建
  • Java——集合类
  • 【Android】屏幕适配小合集
  • 基于python,html,echart,php,mysql,在线实时监控入侵检测系统
  • 六一儿童节礼物清单|雷克赛恩 CyberPro1 打造亲子光影盛宴
  • OptiStruct结构分析与工程应用:结构激励
  • 线程安全问题
  • 100个Linux运维知识
  • Cursor远程连接+工具使用
  • VSCode查询
  • 人工智能如何改变医疗健康行业?
  • 门店自检数字化解决方案:智能任务派发+AI复核实践
  • Strace:深入系统调用的强大调试工具
  • 手机打电话时由对方DTMF响应切换多级IVR语音菜单(完结)