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

Flutter如何在页面渲染前等待Future执行完成 避免冷启动闪登录页

解决方案

核心问题是AppModel初始化时currentUser默认值为null,首次build必然触发LoginPage渲染,等异步数据库查询完成更新状态才会跳转到HomePage,由此产生闪屏。可以通过以下两种方案解决:


方案1:提前初始化用户数据(最优)

你完全可以在main函数的异步阶段完成用户查询,直接给AppModel传入初始值,从根源避免初始currentUser为空的问题:

  1. 改造AppModel构造函数,支持传入初始用户:
class AppModel extends ChangeNotifier {
  User? currentUser;
  // 新增构造参数接收初始用户
  AppModel({User? initialUser}) : currentUser = initialUser;

  // 其余原有逻辑保持不变
}
  1. 修改main函数,初始化Hive后提前查询用户:
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final document = await getApplicationDocumentsDirectory();
  Hive.init(document.path);

  // 新增:提前查询本地用户
  final userDao = UserDao();
  final User? initialUser = await userDao.getCurrentUser(); // 替换为你实际的查用户方法

  runApp(
    Phoenix(
      // 把初始用户传入MyApp
      child: MyApp(initialUser: initialUser),
    ),
  );
}
  1. 改造MyApp,把初始用户传给AppModel:
class MyApp extends StatelessWidget {
  final User? initialUser;
  const MyApp({super.key, required this.initialUser});

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        // 构造AppModel时传入初始值
        ChangeNotifierProvider(create: (c) => AppModel(initialUser: initialUser)),
        Provider(create: (c) => UserDao()),
        // 其余provider保持不变
      ],
      child: MaterialApp(
        title: '_',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: AppScaffold()
      ),
    );
  }
}

改造完成后AppModel初始化时就已经拿到了本地存储的用户信息,首次build会直接渲染HomePage,不会出现LoginPage闪屏。AppScaffold的initState中的GetUserFromDB().run()逻辑可根据业务需求决定是否保留。


方案2:新增启动加载页过渡

如果不希望把用户查询逻辑放在main中,可以在路由判断前加一层启动屏过渡,加载完成后再跳转对应页面:
修改AppScaffold的build逻辑:

class _AppScaffoldState extends State<AppScaffold> {
  late final Future<User?> _loadUserFuture;

  @override
  initState() {
    super.initState();
    // 初始化查询用户的Future
    _loadUserFuture = context.read<UserDao>().getCurrentUser();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<User?>(
      future: _loadUserFuture,
      builder: (context, snapshot) {
        // 加载阶段显示和应用开屏一致的启动页,用户无感知
        if (snapshot.connectionState != ConnectionState.done) {
          return const SplashPage();
        }
        // 加载完成后更新AppModel状态
        final User? currentUser = snapshot.data;
        if (currentUser != null) {
          context.read<AppModel>().currentUser = currentUser;
          return const HomePage(title: 'HomePage');
        } else {
          return const LoginPage(title: 'LoginPage');
        }
      },
    );
  }
}

该方案不需要修改上层初始化逻辑,加载阶段统一显示启动屏,同样不会出现LoginPage闪屏的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 13:09:02