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 {
  @override
  RouteSettings? redirect(String? route) {
    final auth = Get.find<AuthController>();
    if (!auth.isLoggedIn.value) {
      return const RouteSettings(name: '/login');
    }
    return null; // 正常访问
  }

  @override
  int? 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 {
  @override
  Widget 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 {
  @override
  Widget 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 {
  @override
  Widget 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 {
  @override
  Widget 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 {
  @override
  Widget 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 {
    @override
    RouteSettings? 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 类型)

类型 示例 使用说明
RxInt RxInt count = 0.obs; obs 创建响应式变量
RxString var name = ''.obs; 自动追踪变化
RxList RxList items = [].obs; 响应式数组
RxMap RxMap 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}'));

  2. 方法 2:GetX Widget

    GetX<CounterController>(
    builder: (controller) => Text('${controller.count}'),
    );

  3. 方法 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;

  @override
  void 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

  2. 然后运行:

    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 '张三'
int 100
double 3.14
bool true
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;

    复制代码
    @override
    void 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 清理机制
相关推荐
唔665 小时前
网络图片的缓存和压缩
flutter
初遇你时动了情9 小时前
flutter dart 函数语法
flutter
老K(郭云开)15 小时前
最新版Chrome浏览器调用ActiveX控件技术——alWebPlugin中间件V2.0.42版发布
前端·chrome·中间件
爱吃鱼的锅包肉1 天前
记录一下flutter项目自己封窗的弹窗
前端·javascript·flutter
Frank学习路上1 天前
【Flutter】创建BMI计算器应用并添加依赖和打包
前端·javascript·flutter
kirk_wang1 天前
鸿蒙版Flutter库torch_light手电筒功能深度适配
flutter·华为·harmonyos
itachi-uchiha1 天前
Docker安装MinIO对象存储中间件
中间件·容器·minio
初遇你时动了情1 天前
flutter长列表 ListView、GridView、SingleChildScrollView、CustomScrollView区别
前端·javascript·flutter
zhujilisa2 天前
中间件-seata
中间件