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

Flutter:如何实现启动页自动跳转至下一页面?

你的代码里有几个导致启动页无法正常显示并跳转的问题:

  1. 根路由/同时设置了builder(返回SplashScreen)和redirect,GoRouter的redirect会优先执行,导致SplashScreen还没显示就被跳转走了。
  2. 子路由的path写法错误:子路由的path不应该以/开头,比如/login应该改成login,否则会被识别为绝对路径,和父路由的路径拼接出错。
  3. BlocProvider中创建的AuthBloc和传给goRouter的authBloc不是同一个实例,导致状态监听和token检查可能不一致。

以下是修正后的实现方案:

1. 调整路由结构,分离启动页与其他路由

把SplashScreen作为单独的根路由,login、homepage设置为同级路由,避免redirect直接跳过启动页:

GoRouter goRouter(AuthBloc authBloc) {
  return GoRouter(
    navigatorKey: GlobalKey<NavigatorState>(),
    initialLocation: '/',
    routes: <GoRoute>[
      // 启动页路由
      GoRoute(
        path: '/',
        name: 'splash',
        builder: (context, state) => const SplashScreen(),
      ),
      // 登录页路由
      GoRoute(
        path: '/login',
        name: 'login',
        builder: (context, state) => const LoginPage(),
      ),
      // 主页路由
      GoRoute(
        path: '/homepage',
        name: 'homepage',
        builder: (context, state) {
          return BlocProvider<WeatherBloc>(
            create: (context) => WeatherBloc(),
            child: MyHomepage(dateTime: DateTime.now()),
          );
        },
        routes: [
          // 子路由去掉开头的/
          GoRoute(
            path: 'gempa',
            name: 'gempa',
            builder: (context, state) {
              return BlocProvider<GempaBloc>(
                create: (context) => GempaBloc(),
                child: const GempaPage(),
              );
            },
          ),
        ],
      ),
    ],
  );
}

2. 统一AuthBloc实例,在启动页中处理跳转逻辑

确保MyApp中使用同一个AuthBloc实例,然后在SplashScreen内部监听状态变化完成跳转:

class _MyAppState extends State<MyApp> {
  final FirebaseAuthService firebaseAuthService = FirebaseAuthService();
  late final AuthBloc authBloc;

  @override
  void initState() {
    super.initState();
    authBloc = AuthBloc(firebaseAuthService)..add(CheckSignStatus());
  }

  @override
  Widget build(BuildContext context) {
    return BlocProvider.value(
      value: authBloc,
      child: MaterialApp.router(
        title: 'sample',
        routerConfig: goRouter(authBloc),
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          textTheme: GoogleFonts.poppinsTextTheme(Theme.of(context).textTheme),
        ),
      ),
    );
  }
}

编写SplashScreen,在内部监听AuthBloc状态实现跳转:

class SplashScreen extends StatelessWidget {
  const SplashScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocListener<AuthBloc, AuthState>(
      listener: (context, state) {
        if (state is AuthUser) {
          // go方法等效于pushReplacement,替换当前栈顶路由
          context.go('/homepage');
          // 若需完全清除栈可使用replace:context.replace('/homepage');
        } else if (state is NonAuthUser) {
          context.go('/login');
          // 若需完全清除栈可使用replace:context.replace('/login');
        }
      },
      child: const Scaffold(
        body: Center(
          child: Text('启动页...'),
        ),
      ),
    );
  }
}

补充说明

  • GoRouter的context.go()默认替换当前栈顶路由,效果和pushReplacement一致;如果需要清空整个路由栈再跳转,可使用context.replace()。
  • 移除了原根路由的redirect逻辑,改为在SplashScreen中监听状态跳转,确保启动页先显示再执行跳转。
  • 修正了子路由的path写法,子路由path无需以/开头,否则会被解析为绝对路径导致匹配错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 07:26:36