Flutter接入Firebase实现新用户邮箱验证准入及跳转异常排查
问题根因
你代码里最核心的故障点是VerifyPage中的Auth实例没有初始化,声明了AuthBase? auth;但从未赋值,导致auth一直为null,后续取当前用户、校验邮箱验证状态的逻辑全部不会生效,自然无法跳转。
还有两个次要问题:
- 你在创建用户时已经发送过验证邮件,VerifyPage的initState里又重复触发了一次邮件发送,属于多余操作
- 校验逻辑没有处理用户被登出/不存在的边界场景,可能出现静默异常
修复步骤
1. 给VerifyPage增加Auth参数传递
先修改VerifyPage的定义,支持传入Auth实例:
class VerifyPage extends StatefulWidget { const VerifyPage({ Key? key, required this.auth, }) : super(key: key); // 新增接收Auth实例的参数 final AuthBase auth; @override State<VerifyPage> createState() => _VerifyPageState(); }
2. 修改_VerifyPageState的逻辑,移除重复发邮件的代码,补全校验逻辑
class _VerifyPageState extends State<VerifyPage> { // 直接用widget.auth取传入的实例,不再单独声明auth变量 Timer? timer; User? user; @override void initState() { super.initState(); user = widget.auth.currentUser; // 移除多余的sendEmailVerification调用,创建用户时已经发过了 timer = Timer.periodic( const Duration(seconds: 5), (timer) => checkEmailVerified(), ); } Future<void> checkEmailVerified() async { // 每次校验前先重载用户信息 await user?.reload(); // 重载后重新取最新的用户状态 final currentUser = widget.auth.currentUser; if (currentUser != null && currentUser.emailVerified) { timer?.cancel(); if (mounted) { // 增加mounted判断,避免页面销毁后触发导航报错 Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => const JobsPage()), ); } } else if (currentUser == null) { // 用户已登出的场景,直接取消定时器,可按需跳转到登录页 timer?.cancel(); } } @override void dispose() { timer?.cancel(); super.dispose(); } // build方法保持不变即可 @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: Container(), title: const Text('Verify Email'), ), body: const Center( child: Padding( padding: EdgeInsets.all(16.0), child: Text( 'An email has just been sent to your email. Click on the link provided to complete registration.', style: TextStyle( fontSize: 20.0, ), ), ), ), ); } }
3. 修改跳转VerifyPage的代码,传入Auth实例
跳转的时候要把已经初始化好的Auth实例传进去,_submitVerify方法修改参考如下:
Future<void> _submitVerify() async { try { await model.submitVerify(context); // 这里传入你项目中全局共用的Auth实例即可,不要重复创建新实例 Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => VerifyPage(auth: yourGlobalAuthInstance), ), ); } on FirebaseAuthException catch (e) { showExceptionAlertDialog( context, exception: e, title: 'Sign In Failed', ); } }
注意:如果你的项目用了Provider、GetIt等状态管理工具管理Auth实例,不要直接新创建Auth实例,要取全局共用的那个实例,避免实例不一致取不到当前用户。
内容的提问来源于stack exchange,提问作者Carleton Y
相关产品推荐
相关产品推荐

