You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GoRouter新增路由后热重载不生效,寻求支持热重载的配置方案

解决GoRouter新增路由后热重载不生效的问题

你的问题根源在于全局final修饰的GoRouter实例:final变量在热重载时不会重新初始化,GoRouter的路由表是在实例创建时就固定下来的,新增路由后热重载不会更新这个已初始化的路由表,因此会出现路由未找到的错误;而热重启会重新执行整个代码流程,重新创建GoRouter实例,所以路由表能正常加载。

下面是几种可行的解决方案,按推荐程度排序:

方案1:使用GoRouter的refreshListenable参数(推荐)

GoRouter内置了refreshListenable机制,可以通过一个Listenable对象触发路由表的重新构建。热重载时,这个Listenable会自动触发刷新,让新增的路由生效:

// 全局定义一个用于触发路由刷新的Notifier
final routerRefreshNotifier = ValueNotifier<bool>(true);

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'Test App',
      debugShowCheckedModeBanner: false,
      theme: theme(),
      scrollBehavior: const CupertinoScrollBehavior(),
      routerConfig: GoRouter(
        // 传入refreshListenable
        refreshListenable: routerRefreshNotifier,
        routes: [
          GoRoute(
            path: '/sign-in',
            builder: (context, state) => SignInScreen(),
          ),
          GoRoute(
            path: '/home-screen',
            builder: (context, state) => HomeScreen(),
          ),
        ],
      ),
    );
  }
}

后续新增路由后,只需保存代码触发热重载,GoRouter就会自动根据最新的路由表重建,无需热重启。如果需要手动触发路由刷新(比如动态添加路由的场景),只需调用routerRefreshNotifier.value = !routerRefreshNotifier.value即可。

方案2:将GoRouter实例移到Widget的build方法内

把GoRouter的创建逻辑放到MyApp的build方法中,这样热重载时build方法会重新执行,GoRouter实例会被重新初始化,路由表也会同步更新:

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    // 在build方法内创建GoRouter实例
    final appRouter = GoRouter(
      routes: [
        GoRoute(
          path: '/sign-in',
          builder: (context, state) => SignInScreen(),
        ),
        GoRoute(
          path: '/home-screen',
          builder: (context, state) => HomeScreen(),
        ),
      ],
    );

    return MaterialApp.router(
      title: 'Test App',
      debugShowCheckedModeBanner: false,
      theme: theme(),
      scrollBehavior: const CupertinoScrollBehavior(),
      routerConfig: appRouter,
    );
  }
}

这种方式简单直接,但每次build都会重新创建GoRouter实例,对于需要保留路由状态的场景可能不太友好。

方案3:用StatefulWidget动态重建路由

如果需要保留GoRouter的一些状态,可以使用StatefulWidget,在didChangeDependencies方法中重新初始化路由表——热重载时这个方法会被调用,从而更新路由配置:

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late GoRouter _appRouter;

  void _initRouter() {
    _appRouter = GoRouter(
      routes: [
        GoRoute(
          path: '/sign-in',
          builder: (context, state) => SignInScreen(),
        ),
        GoRoute(
          path: '/home-screen',
          builder: (context, state) => HomeScreen(),
        ),
      ],
    );
  }

  @override
  void initState() {
    super.initState();
    _initRouter();
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // 热重载时重新初始化路由
    _initRouter();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'Test App',
      debugShowCheckedModeBanner: false,
      theme: theme(),
      scrollBehavior: const CupertinoScrollBehavior(),
      routerConfig: _appRouter,
    );
  }
}

补充说明

之前使用Navigator 1.0时无需热重启就能生效,是因为Navigator 1.0的路由配置是和Widget树绑定的,热重载时Widget树重建,新的路由配置会被自动加载;而GoRouter的默认实现是将路由表固化在实例中,因此需要通过上述方式让热重载时重新生成路由表。

内容的提问来源于stack exchange,提问作者Sam Adole

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 01:57:39