路由方案选型:主流混合路由方案对比

路由管理,说白了就是页面跳转的「交通指挥系统」。

我在做混合开发时,最头疼的不是业务逻辑,而是页面跳来跳去,参数传丢了、返回栈乱了、动画卡了……这些坑我踩过不少。今天咱们就聊聊 Flutter 里主流的四种路由方案,看看它们各自适合什么场景。

一、Fluro:轻量级的老牌选手

Fluro 是我最早接触的路由库。它很轻,API 也简单。

它的核心思路是「路径匹配 + 处理器」。你定义好路径,然后绑定一个处理器函数。跳转时,Fluro 根据路径找到对应的处理器,执行页面构建。

// Fluro 路由定义示例
var router = Router();
router.define("/user/:id", handler: Handler(
  handlerFunc: (context, parameters) {
    String userId = parameters['id'][0];
    return MaterialPageRoute(
      builder: (context) => UserPage(userId: userId),
    );
  },
));

嗯,这里要注意:Fluro 不支持类型安全的参数传递。参数都是字符串,你得自己解析。我在项目中遇到过传复杂对象时,只能序列化成 JSON 字符串,然后在目标页面再反序列化。说实话,挺麻烦的。

适用场景:小型项目、原型快速开发、对类型安全要求不高的场景。

二、GetX:大而全的「瑞士军刀」

GetX 不只是路由,它还有状态管理、依赖注入、国际化……说白了,它是一个全家桶。

它的路由部分,我个人觉得最方便的是「命名路由 + 参数传递」的写法。你不需要手动创建 MaterialPageRoute,直接传参数就行。

// GetX 路由跳转示例
Get.toNamed("/user", arguments: {"id": "123", "name": "张三"});

// 目标页面接收参数
class UserPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final args = Get.arguments as Map<String, dynamic>;
    return Text("用户ID: ${args['id']}");
  }
}

我曾经在一个中型项目里用 GetX,确实开发效率很高。但后来发现一个问题:GetX 的路由和它的状态管理深度绑定,如果你后期想换状态管理方案,路由也得跟着换。这就有点「上了贼船」的感觉。

避坑指南:GetX 的路由不支持类型安全,参数类型在运行时才能确定。如果你对类型安全有执念,建议慎用。

三、GoRouter:官方推荐的「正规军」

GoRouter 是 Flutter 官方团队维护的路由方案。它基于 Navigator 2.0 设计,支持声明式路由、深度链接、Web 路由等。

我个人习惯用 GoRouter,因为它类型安全、支持泛型参数传递,而且和 Flutter 生态结合得最好。

// GoRouter 路由配置示例
final router = GoRouter(
  routes: [
    GoRoute(
      path: '/user/:id',
      builder: (context, state) {
        final userId = state.pathParameters['id']!;
        return UserPage(userId: userId);
      },
    ),
  ],
);

你想想看,GoRouter 的路径参数是类型安全的,state.pathParameters 返回的是 Map<String, String>,你不用担心类型转换出错。而且它还支持 extra 参数,可以传递任意类型的数据。

我的建议:如果你是新项目,或者项目对路由的灵活性要求较高,优先考虑 GoRouter。它是官方出品,长期维护有保障。

四、自定义 Router:自由但代价高

有些场景下,现成的路由方案满足不了需求。比如你需要复杂的页面过渡动画、自定义的返回栈逻辑、或者和原生端深度交互。

这时候,你可以基于 Navigator 2.0 自己实现一套路由管理。说白了,就是自己写一个 Router 类,管理页面栈、处理路由变化、监听返回事件。

// 自定义 Router 的简化示例
class MyRouter extends RouterDelegate<String> {
  final List<Page<dynamic>> _pages = [];

  @override
  Widget build(BuildContext context) {
    return Navigator(
      pages: _pages,
      onPopPage: (route, result) {
        if (!route.didPop(result)) return false;
        _pages.removeLast();
        return true;
      },
    );
  }

  void pushPage(Page<dynamic> page) {
    setState(() {
      _pages.add(page);
    });
  }
}

我曾经在一个混合开发项目中,需要实现「原生页面和 Flutter 页面共享返回栈」。用 GoRouter 搞不定,最后只能自己写 Router。嗯,那段时间加班加得挺狠的。

警告:自定义 Router 的维护成本很高。除非你有非常特殊的需求,否则不建议自己造轮子。

五、选型决策矩阵

说了这么多,到底选哪个?我整理了一个决策矩阵,你对照着看就行。

评估维度 Fluro GetX GoRouter 自定义 Router
类型安全 ❌ 不支持 ❌ 不支持 ✅ 支持 ✅ 可自行实现
参数传递 仅字符串 支持任意类型 支持泛型 完全可控
深度链接 ❌ 不支持 ❌ 不支持 ✅ 原生支持 需自行实现
Web 路由 ❌ 不支持 ❌ 不支持 ✅ 原生支持 需自行实现
学习成本 中高
维护成本
社区活跃度 低(已停止维护) 高(官方维护)
推荐场景 快速原型 中小型项目 中大型项目 特殊需求

六、我的选型建议

如果你问我个人怎么选,我会这样排序:

  1. 首选 GoRouter:官方出品、类型安全、支持深度链接和 Web 路由。适合大多数项目。
  2. 次选 GetX:如果你已经在用 GetX 做状态管理,那路由也用它,省得引入新依赖。
  3. Fluro 可以放弃了:它已经停止维护,而且不支持类型安全。除非你维护的是老项目,否则别碰。
  4. 自定义 Router 是最后的选择:只有当你发现所有现成方案都满足不了需求时,才考虑自己写。
一句话总结:选路由方案,先看项目规模,再看团队技术栈,最后看特殊需求。别为了炫技选最复杂的,也别为了省事选最简陋的。
路由方案选型决策流程图 开始选型 项目规模? 小型 Fluro(快速原型) 中型 GetX(全家桶) 大型 GoRouter(官方推荐) 特殊需求 → 自定义 Router(最后选择)
专注资料整理