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

Flutter嵌套Navigator的onGenerateRoute未在StreamBuilder触发时调用

问题解决:登录状态变化时页面不跳转的修复

核心问题分析

你当前的实现存在两个关键问题:

  1. 错误嵌套Navigator:每次状态变化时返回全新的Navigator组件,违背Flutter路由管理设计逻辑——Navigator应保持固定层级,而非随状态频繁重建,导致onGenerateRoute仅首次触发。
  2. Auth流异步逻辑缺失:stateChanges方法中user.reload()是异步操作,未用await等待完成,无法实时获取最新的邮箱验证状态。

修复步骤

1. 重构StreamBuilder页面渲染逻辑

删除嵌套的Navigator,直接返回对应状态的页面组件。StreamBuilder会在Auth状态变化时自动重建body,实现页面切换:

return Scaffold(
  body: StreamBuilder<AuthState>(
    stream: Auth.instance.stateChanges(),
    builder: (context, snapshot) {
      if (snapshot.connectionState == ConnectionState.waiting) {
        return const Center(child: CircularProgressIndicator());
      }
      assert(snapshot.connectionState != ConnectionState.done);

      switch(snapshot.data) {
        case AuthState.loggedIn:
          return const MainWidget();
        case AuthState.loggedOut:
          return const LoginWidget();
        case AuthState.verifyEmail:
          return const EmailNotVerWidget();
        default:
          throw Exception('Unknown Auth State');
      }
    },
  ),
);

2. 修复Auth类的stateChanges流

给user.reload()添加await,确保获取最新用户状态:

Stream<AuthState> stateChanges() async* {
  await for (final user in FirebaseAuth.instance.authStateChanges()) {
    if (user == null) {
      yield AuthState.loggedOut;
    } else {
      // 等待reload完成,获取最新邮箱验证状态
      if (!user.emailVerified) {
        await user.reload();
        // 重新获取user对象,reload后原对象不会自动更新
        final updatedUser = FirebaseAuth.instance.currentUser;
        if (updatedUser != null && updatedUser.emailVerified) {
          yield AuthState.loggedIn;
          continue;
        }
      }
      
      if (user.emailVerified) {
        yield AuthState.loggedIn;
      } else {
        yield AuthState.verifyEmail;
      }
    }
  }
}

3. 可选:全局路由管理(进阶)

如果应用有复杂路由需求,可将StreamBuilder放在MaterialApp根节点,通过初始页面指定实现状态驱动的路由:

return MaterialApp(
  home: StreamBuilder<AuthState>(
    stream: Auth.instance.stateChanges(),
    builder: (context, snapshot) {
      if (snapshot.connectionState == ConnectionState.waiting) {
        return const Center(child: CircularProgressIndicator());
      }
      
      Widget initialPage;
      switch(snapshot.data) {
        case AuthState.loggedIn:
          initialPage = const MainWidget();
          break;
        case AuthState.loggedOut:
          initialPage = const LoginWidget();
          break;
        case AuthState.verifyEmail:
          initialPage = const EmailNotVerWidget();
          break;
        default:
          throw Exception('Unknown Auth State');
      }
      
      return initialPage;
    },
  ),
);

关键说明

  • 直接返回页面组件是新手友好方案,依赖StreamBuilder的重建机制自动完成页面切换。
  • 必须处理user.reload()的异步逻辑,否则邮箱验证状态无法实时更新。
  • 避免嵌套Navigator,会导致路由栈混乱和状态更新失效。

内容的提问来源于stack exchange,提问作者Андрій Немченко

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 11:45:33