跳转到正文
YGJoon 技术博客

Flutter路由管理进阶

发布于:
·1.2k 字 · 约 3 分钟·作者:
NavigatorObserver 监听页面进出、登录拦截未登录跳转、canActivate 前置守卫:路由层的权限与埋点管控
Flutter路由管理进阶文章封面
目录

路由拦截

1. 全局路由拦截

class GlobalRouteObserver extends NavigatorObserver {
  @override
  void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
    // 路由被压入栈时的处理
    print('新路由: ${route.settings.name}')
  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
    // 路由被弹出栈时的处理
    print('返回到: ${previousRoute?.settings.name}')
  }
}

2. 自定义路由拦截器

class RouteInterceptor {
  static bool handleRoute(String routeName) {
    // 登录拦截
    if (_needLogin(routeName) && !isLoggedIn) {
      Navigator.pushNamed(context, '/login');
      return false;
    }
    return true;
  }

  static bool _needLogin(String routeName) {
    // 需要登录的路由列表
    return ['/profile', '/settings'].contains(routeName);
  }
}

路由守卫

1. 路由前置守卫

class RouteGuard {
  static Future<bool> canActivate(String routeName) async {
    // 权限检查
    if (!await checkPermission(routeName)) {
      showPermissionDeniedDialog();
      return false;
    }
    
    // 其他条件检查
    if (!meetOtherConditions(routeName)) {
      return false;
    }
    
    return true;
  }
}

2. 路由解析守卫

class RouteResolver extends RouteInformationParser<RouteState> {
  @override
  Future<RouteState> parseRouteInformation(
    RouteInformation routeInformation
  ) async {
    final uri = Uri.parse(routeInformation.location!);
    
    // 路由参数验证
    if (!validateParams(uri.queryParameters)) {
      return RouteState.error();
    }
    
    return RouteState.fromUri(uri);
  }
}

路由状态管理

1. 路由状态持久化

class RouteStateManager {
  // 保存路由历史
  static Future<void> saveRouteHistory(String routeName) async {
    final prefs = await SharedPreferences.getInstance();
    final history = prefs.getStringList('route_history') ?? [];
    history.add(routeName);
    await prefs.setStringList('route_history', history);
  }

  // 恢复路由状态
  static Future<void> restoreRouteState() async {
    final prefs = await SharedPreferences.getInstance();
    final lastRoute = prefs.getString('last_route');
    if (lastRoute != null) {
      Navigator.pushNamed(context, lastRoute);
    }
  }
}

2. 路由栈管理

class RouteStackManager {
  static final List<String> _routeStack = [];

  // 压入路由
  static void push(String routeName) {
    _routeStack.add(routeName);
    _updateRouteState();
  }

  // 弹出路由
  static String? pop() {
    if (_routeStack.isNotEmpty) {
      final route = _routeStack.removeLast();
      _updateRouteState();
      return route;
    }
    return null;
  }

  // 更新路由状态
  static void _updateRouteState() {
    // 处理路由状态变化
  }
}

高级特性

1. 深层链接处理

class DeepLinkHandler {
  static Future<void> handleDeepLink(String link) async {
    final uri = Uri.parse(link);
    
    // 解析深层链接
    final route = parseDeepLink(uri);
    if (route != null) {
      // 处理路由跳转
      await Navigator.pushNamed(context, route);
    }
  }

  static String? parseDeepLink(Uri uri) {
    // 实现深层链接解析逻辑
    return null;
  }
}

2. 路由动画定制

class CustomPageRoute extends PageRouteBuilder {
  final Widget page;

  CustomPageRoute({required this.page})
    : super(
        pageBuilder: (context, animation, secondaryAnimation) => page,
        transitionsBuilder: (context, animation, secondaryAnimation, child) {
          return FadeTransition(
            opacity: animation,
            child: child,
          );
        },
      );
}

最佳实践

1. 路由表集中管理

2. 登录拦截用中间件

3. 404 与参数兜底

4. 深链接按需再做

常见问题

1. 路由参数丢失

2. 返回键行为

3. 内存管理

实战案例

路由”进阶”我理解就是一件事:路由表别散。某物流冷链项目 里我有 RouteNames(纯字符串常量)+ RoutePages.list(GetPage 列表)两层:前者给业务代码跳转用(Get.toNamed(RouteNames.profile)),后者给 GetMaterialApp(getPages:) 注册用。中间件(比如登录拦截)我挂在 GetPage 的 middlewares 上,而不是每个按钮里判登录——之前试过在点击处判,十几个入口漏了两个,被测试抓包。集中式路由表 + 中间件,是我从”能跑”到”可维护”跨过去的关键一步。至于深链接(App Links),这几个项目都没做,有需求再说。

总结

路由进阶归根结底是”集中”:路由表集中、拦截集中、埋点集中。RouteNames + getPages 两层表,登录拦截挂 middleware,NavigatorObserver 做埋点,深链接按需再加。散落在各处的跳转看着灵活,项目一大就是灾难——路由表是应用的索引,值得像数据库表结构一样认真设计。


分享这篇文章:


相关文章

上一篇
Flutter集成微信SDK - Fluwx详解
下一篇
Flutter 基础动画详解