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

Flutter切换应用主题时路由重置问题求助

问题解决:切换主题时保留设置页面路由

问题根源

每次切换主题触发themeMode变化时,MesMaterialApp的build方法会重新执行,而你在build里每次都调用MesAppRouter.getRouter()创建新的GoRouter实例。新的GoRouter会使用initialLocation初始化路由栈,导致当前设置页面被替换,自动回到首页。

解决方案

核心思路是让GoRouter实例保持单例,避免每次主题变更都重建路由栈。通过Riverpod的Provider缓存GoRouter,只在应用启动时初始化一次初始路由位置。

步骤1:用Riverpod Provider管理GoRouter单例

创建一个Provider来提供GoRouter,确保只在应用启动时创建一次:

final goRouterProvider = Provider<GoRouter>((ref) {
  // 仅在Provider初始化时获取一次isOnboarded,后续变更不影响初始路由
  final isOnboarded = ref.watch(settingsProvider.select((s) => s.isOnboarded));
  return MesAppRouter.getRouter(
    initialLocation: isOnboarded ? HomeRoute.path : WelcomeRoute.path,
  );
});

步骤2:修改MesMaterialApp获取Router的方式

在MesMaterialApp的build方法中,从Provider获取缓存的Router,而非每次重建:

class MesMaterialApp extends ConsumerWidget {
  MesMaterialApp({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // 从Provider获取单例Router,不会随主题变更重建
    final router = ref.watch(goRouterProvider);

    final brightness = View.of(context).platformDispatcher.platformBrightness;
    TextTheme textTheme = createTextTheme(context, "Poppins", "Lato");
    AppBarTheme appBarTheme = createAppBarTheme(brightness == Brightness.light);
    MaterialTheme theme = MaterialTheme(textTheme, appBarTheme);

    return MaterialApp.router(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      theme: theme.light(),
      darkTheme: theme.dark(),
      themeMode: ref.watch(settingsProvider.select((s) => s.theme)),
      highContrastTheme: theme.lightHighContrast(),
      highContrastDarkTheme: theme.darkHighContrast(),
      localizationsDelegates: AppLocalizations.localizationsDelegates,
      supportedLocales: AppLocalizations.supportedLocales,
      routerConfig: router,
    );
  }
}

补充:处理isOnboarded后续变更

如果需要在用户完成引导后从Welcome页跳转到首页,不要重建Router,而是在settingsProvider中监听isOnboarded变化,主动导航:

// 在settingsProvider的逻辑中添加监听
ref.listen(settingsProvider.select((s) => s.isOnboarded), (previous, next) {
  if (next == true && previous == false) {
    final router = ref.read(goRouterProvider);
    router.go(HomeRoute.path);
  }
});

这样修改后,切换主题时只会更新themeMode,路由栈保持不变,用户可以停留在设置页面实时看到主题变化效果,和原生Android的行为一致。

内容的提问来源于stack exchange,提问作者Mervin Hemaraju

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 02:50:19