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

Flutter使用MaterialApp.router+GoRouter时全局Overlay加载无法显示

解决GoRouter下全局Overlay加载不显示的问题

问题根源在于你把ref.listen放在了MaterialApp.router的外部,这里的context不属于MaterialApp的上下文树,无法找到Overlay的挂载入口。而旧代码里的监听是在MaterialApp的home参数内部的Consumer中,用的是MaterialApp内部的上下文,能正确访问Overlay。

下面给两种可行的修改方案:

方案一:用MaterialApp.router的builder参数注入监听

把监听逻辑移到MaterialApp.router的builder参数里,这里的context是MaterialApp内部的上下文,能正确获取Overlay:

final router = ref.watch(routerProvider);

return MaterialApp.router(
  title: 'my app',
  theme: ThemeData(
    brightness: Brightness.dark,
    primarySwatch: Colors.blue,
    indicatorColor: Colors.blueGrey,
  ),
  darkTheme: ThemeData.dark(),
  themeMode: ThemeMode.dark,
  debugShowCheckedModeBanner: false,
  routeInformationParser: router.routeInformationParser,
  routerDelegate: router.routerDelegate,
  builder: (context, child) {
    return Consumer(
      builder: (context, ref, child) {
        ref.listen<bool>(isLoadingProvider, (_, isLoading) {
          if (isLoading) {
            LoadingScreen.instance().show(context: context);
          } else {
            LoadingScreen.instance().hide();
          }
        });
        return child!;
      },
    );
  },
);

方案二:在GoRouter的ShellRoute中添加监听

如果你的路由结构用了ShellRoute,可以把监听逻辑放在Shell的builder里,这样所有子路由都会共享这个监听,且上下文正确:

final routerProvider = Provider<GoRouter>((ref) {
  return GoRouter(
    routes: [
      ShellRoute(
        builder: (context, state, child) {
          return Consumer(
            builder: (context, ref, child) {
              ref.listen<bool>(isLoadingProvider, (_, isLoading) {
                if (isLoading) {
                  LoadingScreen.instance().show(context: context);
                } else {
                  LoadingScreen.instance().hide();
                }
              });
              return child!;
            },
          );
        },
        routes: [
          GoRoute(path: '/', builder: (context, state) => const MainView()),
          GoRoute(path: '/auth', builder: (context, state) => const AuthPage()),
          // 其他路由...
        ],
      ),
    ],
  );
});

关键说明

不管哪种方案,核心都是确保调用LoadingScreen.show时用的是MaterialApp.router内部的上下文——只有这样,Overlay.of(context)才能找到正确的Overlay实例,加载弹窗才能正常挂载到全局层级。

内容的提问来源于stack exchange,提问作者omar hadek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 03:05:28