showDialog()-尝试根据从Firebase身份验证API调用检索到的错误消息触发对话框模式

showDialog()-尝试根据从Firebase身份验证API调用检索到的错误消息触发对话框模式,firebase,flutter,dart,firebase-authentication,Firebase,Flutter,Dart,Firebase Authentication,我正在尝试为我的应用程序建立错误处理 后端是Firebase 预期功能: 如果API调用返回带有错误消息的响应 确定错误消息的内容,并显示适合该错误消息的文本,以及 根据API调用的错误响应,部署模式以显示特定的错误消息 我认为Auth类中建立的HttpException逻辑没有通过提供程序传递,因此HttpException catch(error)上的方法调用的是HttpException,而不是Auth提供程序中建立的逻辑 代码仍在运行,只有终端显示错误。Modal不部署 下面是我收到

我正在尝试为我的应用程序建立错误处理

后端是Firebase

预期功能:

  • 如果API调用返回带有错误消息的响应
  • 确定错误消息的内容,并显示适合该错误消息的文本,以及
  • 根据API调用的错误响应,部署模式以显示特定的错误消息
我认为Auth类中建立的HttpException逻辑没有通过提供程序传递,因此HttpException catch(error)上的方法
调用的是HttpException,而不是Auth提供程序中建立的逻辑

代码仍在运行,只有终端显示错误。Modal不部署

下面是我收到的错误API调用的示例:

I/flutter (29822): {error: {code: 400, message: EMAIL_NOT_FOUND, errors: [{message: EMAIL_NOT_FOUND, domain: global, reason: invalid}]}}
我正在尝试将错误响应中的消息作为目标

final responseData = json.decode(response.body);
      if (responseData['error'] != null) {
        //if the API call retrieves an error
        throw HttpException(
          //throw custom error handling method
          message: responseData['error']['message'],
          //display the error message returned in the API call (the value assigned to the message within the error array)
        );
      }
然后通过提供者传递它

保存API调用的提供程序:

class Auth with ChangeNotifier {
  String _token;
  DateTime _tokenExpirationDate;
  String _userID;

  final String apiKey = #; //redacted

  //AUTHENTICATION method - extracted to reduce reuse of code
  Future<void> _authenticate(
      {String email, String password, String urlSegment}) async {
    final url = Uri.parse(
        'https://identitytoolkit.googleapis.com/v1/accounts:$urlSegment?key=$apiKey');
    //.parse method allows the use of the full url
    try {
      final response = await http.post(
        url,
        body: json.encode({
          'email': email,
          'password': password,
          'returnSecureToken': true,
        }),
      );
      final responseData = json.decode(response.body);
      if (responseData['error'] != null) {
        //if the API call retrieves an error
        throw HttpException(
          //throw custom error handling method
          message: responseData['error']['message'],
          //display the error message returned in the API call (the value assigned to the message within the error array)
        );
      }
      print(response.statusCode);
    } catch (error) {
      throw error;
    }
  }

  //AUTHENTICATION CREATE API call - Register user
  Future<void> signup(String email, String password) async {
    _authenticate(
      email: email,
      password: password,
      urlSegment: 'signUp',
    );
  }

//AUTHENTICATION READ API call - user sign in
  Future<void> signin(String email, String password) async {
    _authenticate(
      email: email,
      password: password,
      urlSegment: 'signInWithPassword',
    );
  }
}
显示UI和交互逻辑的身份验证卡:

  //VOID function to display a dialog modal. We will use this to display a dialog modal and populate the message with whatever error message the API call returns
  void _errorDialog({String message}) {
    showDialog(
      //in the case that an error occurs, by us putting the return in front of showDialog, showDialog will fulfill that Future in case of the error. If there is no error the .then will fulfill the expected Future value
      context: context,
      builder: (ctx) => AlertDialog(
        title: Text('An error occurred'),
        content: Text(message),
        //we will change the value of message to display according to what the API call returns
        actions: [
          TextButton(
            child: Text('Okay'),
            onPressed: () {
              Navigator.of(ctx).pop();
            },
          ),
        ],
      ),
    );
  }

  //SUBMIT button logic
  Future<void> _submit() async {
    if (!_formKey.currentState.validate()) {
      // Invalid!
      return;
    }
    //Invalid response from user
    _formKey.currentState.save();
    setState(() {
      _isLoading = true;
    });
    //ATTEMPT TO MAKE API CALLS BASED ON ENUM STATE OF DISPLAY
    try {
      if (_authMode == AuthMode.Login) {
        //USER LOGIN
        //call the sign in (read) API
        await Provider.of<Auth>(context, listen: false).signin(
          _authData['email'],
          _authData['password'],
        );
      } else {
        //REGISTER USER
        //call the register (create) API
        await Provider.of<Auth>(context, listen: false).signup(
          _authData['email'],
          _authData['password'],
        );
      }
    } on HttpException catch (error) {
      //we are conducting a filter on the type of errors we want to handle within this block.
      //here we are calling on the HttpException
      var httpErrorMessage = 'Could not login or sign up.';
      //all of the following error messages were retrieved from the Firebase Auth API documentation
      if (error.toString().contains('EMAIL_EXISTS')) {
        //if the API call retrieves a value of 'EMAIL_EXISTS' in the error message
        httpErrorMessage = 'This email is alreary in use';
        //display the above error message
      } else if (error.toString().contains('INVALID_EMAIL')) {
        //if the API call retrieves a value of 'INVALID_EMAIL' in the error message
        httpErrorMessage = 'This is not a valid email.';
        //display the above error message
      } else if (error.toString().contains('INVALID_EMAIL')) {
        //if the API call retrieves a value of 'INVALID_EMAIL' in the error message
        httpErrorMessage = 'This is not a valid email.';
        //display the above error message
      } else if (error.toString().contains('EMAIL_NOT_FOUND')) {
        //if the API call retrieves a value of 'EMAIL_NOT_FOUND' in the error message
        httpErrorMessage = 'Could not find a user with that email.';
        //display the above error message
      } else if (error.toString().contains('INVALID_PASSWORD')) {
        //if the API call retrieves a value of 'INVALID_PASSWORD' in the error message
        httpErrorMessage = 'Invalid password.';
        //display the above error message
      }
      _errorDialog(message: httpErrorMessage);
      //call the error dialog method
      //display in the message whatever defined message to display according to the API error response
    } catch (error) {
      //calling on the error that was established in the Auth class catch(error) {throw error} method in the addProduct function
      const errorMessage =
          'Experiencing network difficulties. Please try again';
      _errorDialog(message: errorMessage);
      //call the error dialog method
      //display in the message whatever defined message to display according to the API error response
    }
    setState(() {
      _isLoading = false;
    });
  }

//用于显示对话框模式的VOID函数。我们将使用它来显示对话框模式,并用API调用返回的任何错误消息填充消息
void\u error对话框({String message}){
显示对话框(
//在发生错误的情况下,通过将返回值放在showDialog前面,showDialog将在出现错误的情况下实现该未来。如果没有错误,则将实现预期的未来值
上下文:上下文,
生成器:(ctx)=>AlertDialog(
标题:文本(“发生错误”),
内容:文本(信息),
//我们将根据API调用返回的内容更改要显示的消息的值
行动:[
文本按钮(
child:Text('ok'),
已按下:(){
Navigator.of(ctx.pop();
},
),
],
),
);
}
//提交按钮逻辑
Future\u submit()异步{
如果(!\u formKey.currentState.validate()){
//无效!
返回;
}
//来自用户的无效响应
_formKey.currentState.save();
设置状态(){
_isLoading=true;
});
//尝试根据显示的枚举状态进行API调用
试一试{
if(_authMode==authMode.Login){
//用户登录
//调用登录(读取)API
等待提供程序。of(上下文,侦听:false)。登录(
_authData['email'],
_authData['password'],
);
}否则{
//注册用户
//调用寄存器(创建)API
等待提供者。of(上下文,listen:false)。注册(
_authData['email'],
_authData['password'],
);
}
}关于HttpException捕获(错误){
//我们正在对要在此块中处理的错误类型进行筛选。
//这里我们调用HttpException
var httpErrorMessage='无法登录或注册';
//以下所有错误消息都是从Firebase Auth API文档中检索到的
if(error.toString()包含('EMAIL_EXISTS')){
//如果API调用在错误消息中检索到“EMAIL\u EXISTS”值
httpErrorMessage='此电子邮件已在使用';
//显示上述错误消息
}else if(error.toString()包含('INVALID_EMAIL')){
//如果API调用在错误消息中检索到值“INVALID_EMAIL”
httpErrorMessage='这不是一封有效的电子邮件';
//显示上述错误消息
}else if(error.toString()包含('INVALID_EMAIL')){
//如果API调用在错误消息中检索到值“INVALID_EMAIL”
httpErrorMessage='这不是一封有效的电子邮件';
//显示上述错误消息
}else if(error.toString()包含('EMAIL\u NOT\u FOUND')){
//如果API调用在错误消息中检索到值“EMAIL\u NOT\u FOUND”
httpErrorMessage='找不到包含该电子邮件的用户';
//显示上述错误消息
}else if(error.toString()包含('INVALID_PASSWORD')){
//如果API调用在错误消息中检索到“INVALID_PASSWORD”值
httpErrorMessage='无效密码';
//显示上述错误消息
}
_errorDialog(消息:httpErrorMessage);
//调用错误对话框方法
//在消息中显示根据API错误响应定义的要显示的任何消息
}捕获(错误){
//调用addProduct函数中的Auth类catch(error){throw error}方法中建立的错误
常量错误消息=
“遇到网络问题,请重试”;
_errorDialog(消息:errorMessage);
//调用错误对话框方法
//在消息中显示根据API错误响应定义的要显示的任何消息
}
设置状态(){
_isLoading=false;
});
}

我没有在登录、注册未来方法中返回任何内容。我需要返回_authenticate方法:

//AUTHENTICATION CREATE API call - Register user
  Future<void> signup(String email, String password) async {
    return _authenticate(
      email: email,
      password: password,
      urlSegment: 'signUp',
    );
  }

//AUTHENTICATION READ API call - user sign in
  Future<void> signin(String email, String password) async {
    return _authenticate(
      email: email,
      password: password,
      urlSegment: 'signInWithPassword',
    );
  }
//身份验证创建API调用-注册用户
未来注册(字符串电子邮件、字符串密码)异步{
返回\u验证(
电邮:电邮,,
密码:密码,
urlSegment:'注册',
);
}
//身份验证读取API调用-用户登录
未来登录(字符串电子邮件、字符串密码)异步{
返回\u验证(
电邮:电邮,,
密码:密码,
URLSEMENT:“signInWithPassword”,
);
}
//AUTHENTICATION CREATE API call - Register user
  Future<void> signup(String email, String password) async {
    return _authenticate(
      email: email,
      password: password,
      urlSegment: 'signUp',
    );
  }

//AUTHENTICATION READ API call - user sign in
  Future<void> signin(String email, String password) async {
    return _authenticate(
      email: email,
      password: password,
      urlSegment: 'signInWithPassword',
    );
  }