Flutter登录页AlertDialog不弹出问题求助
登录错误提示弹窗不显示问题排查与修复
问题描述
登录页面中,当用户输入错误邮箱或密码时,AlertDialog无法弹出,仅CircularProgressIndicator转动后停止。此前已修正过Navigator.pop使用不当导致的黑屏问题,但弹窗问题仍存在。
问题根源
核心问题在于signUserIn函数中Navigator.pop(context)的执行时机错误:无论登录成功或失败,代码最后都会执行该语句,导致错误弹窗的显示逻辑被打断。具体来说,登录失败时,错误弹窗的showDialog刚触发,就被后续的Navigator.pop关闭了进度条弹窗,此时错误弹窗的上下文环境已失效,无法正常显示。
此外,代码未对输入内容做去空格处理,若用户输入前后带有空格,也可能触发不必要的错误提示,且缺少mounted判断,存在widget已销毁时调用Navigator的风险。
修复后的LoginPage代码
import 'package:bet_corner/components/my_textfield.dart'; import 'package:bet_corner/constants/text_strings.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import '../components/my_buttons.dart'; import '../components/square_tile.dart'; class LoginPage extends StatefulWidget { const LoginPage({Key? key}) : super(key: key); @override State<LoginPage> createState() => _LoginPageState(); } class _LoginPageState extends State<LoginPage> { final emailController = TextEditingController(); final passwordController = TextEditingController(); void signUserIn() async { // 显示进度弹窗,禁止点击外部关闭 showDialog( context: context, barrierDismissible: false, builder: (context) { return const Center( child: CircularProgressIndicator(), ); }, ); try { // 对输入内容去空格,避免因空格导致的错误 await FirebaseAuth.instance.signInWithEmailAndPassword( email: emailController.text.trim(), password: passwordController.text.trim(), ); // 登录成功后关闭进度弹窗 if (mounted) Navigator.pop(context); } on FirebaseAuthException catch (e) { // 登录失败,先关闭进度弹窗 if (mounted) Navigator.pop(context); // 根据错误码显示对应弹窗 if (e.code == 'user-not-found') { wrongEmailMessage(); } else if (e.code == 'wrong-password') { wrongPasswordMessage(); } } catch (e) { // 处理其他未知错误 if (mounted) Navigator.pop(context); if (mounted) { showDialog( context: context, builder: (context) { return AlertDialog( title: Text('登录失败: ${e.toString()}'), ); }, ); } } } void wrongEmailMessage() { showDialog( context: context, builder: (context) { return const AlertDialog( title: Text('邮箱错误'), ); }, ); } void wrongPasswordMessage() { showDialog( context: context, builder: (context) { return const AlertDialog( title: Text('密码错误'), ); }, ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[300], body: SafeArea( child: Center( child: SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const SizedBox(height: 100), const Icon( Icons.lock, size: 100, ), const SizedBox(height: 50), Text( jLoginTitle, style: TextStyle(color: Colors.grey[700], fontSize: 17), ), const SizedBox(height: 25), MyTextField( controller: emailController, hintText: 'Email', obscureText: false, ), const SizedBox(height: 10), MyTextField( controller: passwordController, hintText: 'Password', obscureText: true, ), const SizedBox(height: 20), Padding( padding: const EdgeInsets.symmetric(horizontal: 25.0), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text( 'Forgot Password?', style: TextStyle(color: Colors.grey[600]), ), ], ), ), const SizedBox(height: 10), // 登录按钮 MyButton( onTap: signUserIn, ), const SizedBox(height: 50), // 或通过其他方式登录 Padding( padding: const EdgeInsets.symmetric(horizontal: 25.0), child: Row( children: [ Expanded( child: Divider( thickness: 0.5, color: Colors.grey[400], ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 10.0), child: Text( 'Or continue with', style: TextStyle(color: Colors.grey[700]), ), ), Expanded( child: Divider( thickness: 0.5, color: Colors.grey[400], ), ), ], ), ), const SizedBox(height: 50), // Google和Apple登录按钮 Row( mainAxisAlignment: MainAxisAlignment.center, children: const [ SquareTile(imagePath: 'assets/images/google.png'), SizedBox(width: 25), SquareTile(imagePath: 'assets/images/apple.png') ], ), const SizedBox(height: 50), // 注册引导 Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( 'Not a member?', style: TextStyle(color: Colors.grey[700]), ), const SizedBox(width: 4), const Text( 'Register now', style: TextStyle( color: Colors.blue, fontWeight: FontWeight.bold, ), ), ], ) ], ), ), ), ), ); } }
MyTextField组件说明
自定义的MyTextField组件代码无问题,无需修改,其实现了基础的输入框样式和功能,可继续使用:
import 'package:flutter/material.dart'; class MyTextField extends StatelessWidget { final controller; final String hintText; final bool obscureText; const MyTextField({ Key? key, this.controller, required this.hintText, required this.obscureText, }) : super(key: key); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 25.0), child: TextField( controller: controller, obscureText: obscureText, decoration: InputDecoration( enabledBorder: const OutlineInputBorder( borderSide: BorderSide(color: Colors.white), ), focusedBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.grey.shade400), ), fillColor: Colors.grey.shade200, filled: true, hintText: hintText, hintStyle: TextStyle(color: Colors.grey[500])), ), ); } }
内容的提问来源于stack exchange,提问作者Jesse Josiah
相关产品推荐
相关产品推荐

