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

如何为集成Routemaster的Flutter应用添加启动屏并解决闪屏问题?

解决方案:解决启动闪屏问题并实现正确的登录状态路由跳转

问题根源

你的代码中,当Firebase Auth返回已登录用户时,会异步调用getData获取用户数据,但routesBuilder会立刻执行——此时userModel还未加载完成,因此会先返回未登录路由(显示登录页),等异步操作完成后才更新状态切换到首页,这就是启动时闪登录页的核心原因。

下面是修正后的完整方案:


1. 创建启动屏页面

先实现一个展示Logo和加载状态的启动屏,替换成你自己的资源即可:

import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // 替换为你的应用Logo路径
            Image.asset(
              'assets/app_logo.png',
              width: 140,
              height: 140,
            ),
            const SizedBox(height: 30),
            const CircularProgressIndicator(strokeWidth: 3),
          ],
        ),
      ),
    );
  }
}

2. 优化状态监听逻辑(RiverProvider)

在auth_controller.dart中添加一个组合Provider,统一监听Firebase Auth状态和用户数据加载过程,避免状态不一致:

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:firebase_auth/firebase_auth.dart';
import '../models/user_model.dart';

// 原有的authStateChangeProvider保持不变
final authStateChangeProvider = StreamProvider<User?>((ref) {
  return FirebaseAuth.instance.authStateChanges();
});

// 新增:组合监听Auth状态+用户数据加载
final authStateWithUserProvider = FutureProvider<UserModel?>((ref) async {
  // 先等待Auth状态返回
  final authUser = await ref.watch(authStateChangeProvider.future);
  if (authUser == null) return null;
  
  // 再加载用户详细数据(复用你原有的getUserData方法)
  return ref.watch(authControllerProvider.notifier)
      .getUserData(authUser.uid)
      .first;
});

3. 修改main.dart的路由逻辑

简化MyApp组件,通过新的组合Provider监听状态,确保在加载完成前始终显示启动屏:

import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:my_first_flutter_app/core/common/error_text.dart';
import 'package:my_first_flutter_app/features/auth/controller/auth_controller.dart';
import 'package:my_first_flutter_app/firebase_options.dart';
import 'package:my_first_flutter_app/models/user_model.dart';
import 'package:my_first_flutter_app/router.dart';
import 'package:my_first_flutter_app/theme/pallete.dart';
import 'package:my_first_flutter_app/screens/splash_screen.dart'; // 导入启动屏
import 'package:routemaster/routemaster.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  runApp(
    const ProviderScope(
      child: MyApp(),
    ),
  );
}

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

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return MaterialApp.router(
      debugShowCheckedModeBanner: false,
      title: 'My Flutter App',
      theme: ref.watch(themeNotifierProvider),
      routerDelegate: RoutemasterDelegate(
        routesBuilder: (context) {
          // 监听完整的登录状态流程
          return ref.watch(authStateWithUserProvider).when(
                // 加载中:始终返回启动屏路由
                loading: () => RouteMap(routes: {
                  '/': (_) => const MaterialPage(child: SplashScreen()),
                }),
                // 出错:显示错误页面
                error: (error, stackTrace) => RouteMap(routes: {
                  '/': (_) => MaterialPage(child: ErrorText(error: error.toString())),
                }),
                // 状态确定:根据用户数据跳转对应页面
                data: (userModel) {
                  if (userModel != null) {
                    // 更新全局用户状态
                    ref.read(userProvider.notifier).update((_) => userModel);
                    return loggedInRoute;
                  } else {
                    return loggedOutRoute;
                  }
                },
              );
        },
      ),
      routeInformationParser: const RoutemasterParser(),
    );
  }
}

4. 保留原router.dart不变

你的router.dart可以继续使用,无需修改:

import 'package:flutter/material.dart';
import 'package:my_first_flutter_app/features/auth/screen/login_screen.dart';
import 'package:my_first_flutter_app/features/home/screens/home_screen.dart';
import 'package:routemaster/routemaster.dart';

final loggedOutRoute = RouteMap(routes: {
  '/': (_) => const MaterialPage(child: LoginScreen()),
});

final loggedInRoute = RouteMap(routes: {
  '/': (_) => const MaterialPage(child: HomeScreen()),
});

核心改进说明

  • 彻底避免了routesBuilder中执行异步操作导致的路由提前跳转问题,确保在用户状态完全确定前,始终显示启动屏。
  • 通过组合Provider统一管理Auth状态和用户数据加载流程,消除了状态不一致的可能性。
  • 启动屏会持续显示到Firebase Auth状态返回、用户数据加载完成,完美解决网络慢时的闪屏问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 11:37:49