GetX框架里容易被忽略的那些小知识(二)

1,407 阅读5分钟

GetX 中间件(Middleware)是 GetX 框架中对路由进行控制和拦截的重要功能模块。通过中间件可以在用户进入页面前对请求进行检测、处理或重定向,从而在应用导航时执行自定义逻辑。中间件不仅用于权限管理和身份验证,还可以实现缓存、请求限流等多种功能。

1. 中间件的作用

在 GetX 中,中间件的主要运用场景包括但不限于以下几个:

  1. 身份验证:在用户访问受保护的页面时检查其身份状态。

  2. 权限管理:判断用户是否有权限访问特定的页面。

  3. 引导页逻辑:在用户首次打开应用时跳转到引导页。

  4. 页面缓存:在页面打开时进行缓存检查,避免重复加载。

  5. 请求限流:对短时间内频繁的请求进行限制(如防止快速重复提交表单)。

  6. 数据加载:在用户进入页面之前预加载数据,以便页面加载更流畅。

2. 如何使用中间件

在 GetX 中,可以通过自定义 GetMiddleware 类来实现中间件,并在路由配置中将中间件添加到指定的路由上。以下是一个用于检查用户是否已登录的中间件示例。

2.1 创建自定义中间件

创建检查用户是否已登录的中间件。

import 'package:get/get.dart';

class AuthMiddleware extends GetMiddleware {
  // 重写 priority 属性定义中间件的优先级,数值越小优先级越高
  @override
  int? priority = 1;

  // 重写 onPageCalled 方法检查用户是否已登录
  @override
  RouteSettings? redirect(String? route) {
    // 模拟获取用户的登录状态(实际中应从 AuthController 或 AuthService 获取)
    bool isLoggedIn = false; // 假设用户未登录

    if (!isLoggedIn) {
      // 如果用户未登录,重定向到登录页
      return RouteSettings(name: '/login');
    }
    // 如果用户已登录,允许访问目标页面
    return null;
  }
}

2.2 在路由配置中应用中间件

将中间件应用到路由上,可以在路由的 middlewares 参数中传入自定义的中间件。

import 'package:get/get.dart';
import '../pages/home_page.dart';
import '../pages/login_page.dart';
import '../middleware/auth_middleware.dart';

class AppRoutes {
  static final routes = [
    GetPage(
      name: '/home',
      page: () => HomePage(),
      middlewares: [AuthMiddleware()], // 应用 AuthMiddleware 到 home 页面
    ),
    GetPage(
      name: '/login',
      page: () => LoginPage(),
    ),
  ];
}

2.3 启动 GetMaterialApp 并添加路由

在 main.dart 文件中,配置 GetMaterialApp 并添加路由表。

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Middleware Demo',
      initialRoute: '/home',
      getPages: AppRoutes.routes,
    );
  }
}

2.4 中间件完整生命周期

GetMiddleware 提供了多种生命周期方法,用于更精细地控制路由行为:

redirect:在页面构建之前调用,可用于路由重定向。返回 RouteSettings 用于指定新的页面,或返回 null 以继续原始页面的导航。

RouteSettings? redirect(String? route);

onPageCalled:在页面构建前执行,可以用于检查或初始化数据。通常和 redirect 配合使用。

GetPage? onPageCalled(GetPage? page);

onBindingsStart:在页面的 Binding 初始化之前执行,适合提前准备数据。

void onBindingsStart(GetPage? page);

onPageBuildStart:在页面构建开始前执行,可以设置页面初始状态或进行预处理。

GetPageBuilder onPageBuildStart(GetPageBuilder page);

onPageBuilt:在页面构建完成后调用,用于对页面完成后的额外操作。

Widget onPageBuilt(Widget page);

onPageDispose:在页面被释放时调用,可以用于清理资源。

void onPageDispose();

3. 经典示例

3.1 实现权限控制中间件

假设我们有多个权限等级的页面,用户根据权限不同访问的页面不同。

import 'package:get/get.dart';

class PermissionMiddleware extends GetMiddleware {
  final int permissionLevel; // 定义需要的权限等级

  PermissionMiddleware(this.permissionLevel);

  @override
  RouteSettings? redirect(String? route) {
    int userPermissionLevel = 1; // 假设用户当前权限等级为 1

    if (userPermissionLevel < permissionLevel) {
      // 如果用户权限不足,重定向到无权限页面
      return RouteSettings(name: '/no-permission');
    }
    return null;
  }
}

应用此中间件。

import 'package:get/get.dart';
import '../middleware/permission_middleware.dart';
import '../pages/restricted_page.dart';

class AppRoutes {
  static final routes = [
    GetPage(
      name: '/restricted',
      page: () => RestrictedPage(),
      middlewares: [PermissionMiddleware(2)], // 需要权限等级 2
    ),
    GetPage(
      name: '/no-permission',
      page: () => NoPermissionPage(),
    ),
  ];
}

3.2 新用户引导页中间件

在用户首次打开应用时跳转到引导页,而非首页。

import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';

class OnboardingMiddleware extends GetMiddleware {
  @override
  RouteSettings? redirect(String? route) async {
    final prefs = await SharedPreferences.getInstance();
    bool isFirstOpen = prefs.getBool('isFirstOpen') ?? true;

    if (isFirstOpen) {
      // 如果是首次打开,跳转到引导页
      prefs.setBool('isFirstOpen', false); // 更新状态
      return RouteSettings(name: '/onboarding');
    }
    return null;
  }
}

应用引导页中间件。

import 'package:get/get.dart';
import '../middleware/onboarding_middleware.dart';
import '../pages/home_page.dart';
import '../pages/onboarding_page.dart';

class AppRoutes {
  static final routes = [
    GetPage(
      name: '/home',
      page: () => HomePage(),
      middlewares: [OnboardingMiddleware()],
    ),
    GetPage(
      name: '/onboarding',
      page: () => OnboardingPage(),
    ),
  ];
}

3.3 身份验证中间件

创建一个中间件,用于判断用户是否已登录。如果用户未登录,则重定向到登录页。

import 'package:get/get.dart';

class AuthMiddleware extends GetMiddleware {
  @override
  int? priority = 1;

  // 在进入页面之前进行身份验证
  @override
  RouteSettings? redirect(String? route) {
    bool isLoggedIn = false; // 假设从某服务获取登录状态
    if (!isLoggedIn) {
      // 如果用户未登录,重定向到登录页面
      return RouteSettings(name: '/login');
    }
    return null; // 继续导航到目标页面
  }
}

应用此中间件。

import 'package:get/get.dart';
import '../pages/home_page.dart';
import '../pages/login_page.dart';
import '../middleware/auth_middleware.dart';

class AppRoutes {
  static final routes = [
    GetPage(
      name: '/home',
      page: () => HomePage(),
      middlewares: [AuthMiddleware()], // 通过 AuthMiddleware 验证
    ),
    GetPage(
      name: '/login',
      page: () => LoginPage(),
    ),
  ];
}

4. 总结

通过中间件,GetX 可以灵活地实现多种控制场景,轻松实现权限控制、用户引导、页面预处理等多种功能,使应用更具安全性和灵活性。在开发中可以根据业务需求自定义中间件来控制路由行为,确保用户的导航体验与安全需求满足应用的各项规范和需求。