Flutter登录异常时SnackBar无法显示的问题求助
问题:登录错误时SnackBar不显示
我在独立Dart文件中封装了SnackBar的ErrorAlert组件,在登录方法的异常捕获块中传入context和错误信息调用该组件,但触发登录错误(如邮箱格式错误)时,SnackBar并未显示。
组件代码
import 'package:flutter/material.dart'; import 'package:app/globals.dart' as globals; class ErrorAlert{ showAlert(context, message) { return ScaffoldMessenger.of(context).showSnackBar( SnackBar( backgroundColor: globals.mainColor, content: Text(message), duration: const Duration(seconds: 5), action: SnackBarAction( label: 'Dismiss', textColor: Colors.white, onPressed: () { ScaffoldMessenger.of(context).hideCurrentSnackBar(); }, ), ) ); } }
登录方法代码
signInWithEmailIdAndPassword(email,password, context) async { try { UserCredential result = await fireAuth.signInWithEmailAndPassword(email: email, password: password); User user = result.user!; // checkUser = user; //returns UserID if(result != null) { Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => const HomeScreen())); } } catch(signError) { if(signError is PlatformException) { if(signError.code == 'ERROR_WRONG_PASSWORD') { ErrorAlert().showAlert(context, 'Wrong Password!'); } else if(signError.code == 'ERROR_INVALID_EMAIL') { ErrorAlert().showAlert(context, 'Invalid Email ID!'); } else if(signError.code == 'ERROR_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL') { ErrorAlert().showAlert(context, 'Account is already exists with different credentials!'); } else if(signError.code == 'ERROR_USER_NOT_FOUND') { ErrorAlert().showAlert(context, 'User not found!'); } print(signError); } } // return checkUser; }
控制台日志
E/RecaptchaCallWrapper(32567): Initial task failed for action RecaptchaAction(action=signInWithPassword)with exception - The email address is badly formatted.
解决方案
1. 修正异常类型判断
当前代码捕获的是PlatformException,但Firebase Auth最新版本抛出的是FirebaseAuthException,导致异常没进入判断分支,SnackBar自然不会触发。同时Firebase的错误码已更新,比如原ERROR_INVALID_EMAIL现在是invalid-email,需要同步修改:
修改后的登录方法异常捕获部分:
catch(signError) { if(signError is FirebaseAuthException) { switch(signError.code) { case 'wrong-password': ErrorAlert().showAlert(context, '密码错误!'); break; case 'invalid-email': ErrorAlert().showAlert(context, '邮箱格式无效!'); break; case 'account-exists-with-different-credential': ErrorAlert().showAlert(context, '该邮箱已绑定其他登录方式!'); break; case 'user-not-found': ErrorAlert().showAlert(context, '用户不存在!'); break; default: ErrorAlert().showAlert(context, signError.message ?? '登录失败,请稍后重试'); } print(signError); } else { // 处理其他类型异常 ErrorAlert().showAlert(context, '登录失败,请稍后重试'); } }
注意需要导入firebase_auth包:import 'package:firebase_auth/firebase_auth.dart';
2. 确保Context有效性
如果调用登录方法的context不是当前页面Scaffold的上下文(比如直接用MaterialApp的context),ScaffoldMessenger找不到对应的Scaffold,SnackBar也无法显示。解决方法:
- 在登录按钮外层套一个
Builder组件,用Builder的context传入登录方法:
Builder( builder: (ctx) { return ElevatedButton( onPressed: () => signInWithEmailIdAndPassword(email, password, ctx), child: const Text('登录'), ); }, )
- 或者使用全局
ScaffoldMessengerKey,无需传context更方便:- 在全局文件(比如globals.dart)中定义:
final GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();- 在MaterialApp中配置:
MaterialApp( scaffoldMessengerKey: scaffoldMessengerKey, // ...其他配置 )- 修改ErrorAlert组件:
class ErrorAlert{ static showAlert(String message) { return globals.scaffoldMessengerKey.currentState?.showSnackBar( SnackBar( backgroundColor: globals.mainColor, content: Text(message), duration: const Duration(seconds: 5), action: SnackBarAction( label: '关闭', textColor: Colors.white, onPressed: () { globals.scaffoldMessengerKey.currentState?.hideCurrentSnackBar(); }, ), ) ); } }- 调用时无需传context:
ErrorAlert.showAlert('邮箱格式无效!');
3. 额外检查
- 确认
globals.mainColor是可见的颜色,避免SnackBar背景色和内容色接近导致看不见 - 确保登录方法执行时,当前页面还未被Navigator跳转(异常发生时不会执行
Navigator.pushReplacement)
内容的提问来源于stack exchange,提问作者Dhanrajsinh Parmar
相关产品推荐
相关产品推荐

