Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I pass up (in the method stack) an Exception in Flutter?

I'm trying to make an REST app that uses "HTTP Get" communication to login in Flutter. While I had no problem importing "http/http.dart" package and running the http class methods, I encountered a problem with exception handling in Dart/Flutter. I created a method to call http, but if the connectivity is down for any reason, it will naturally return a "SocketException" exception. I have no problem handling the exception in the same method who made the get request, but if I try to pass it up in the caller method stack to the parent method, I just can't catch it again. I found the "rethrow" keyword, but so far, had no success in rethrowing the exception. Below are some methods I use in my code, both the login method and the caller method:

static Future<JsonEnvelop> loginUser(String email, String passwd) async {

    List<int> content = Utf8Encoder().convert(passwd);
    crypto.Digest digest = crypto.md5.convert(content);

    String url = _baseUrl + _loginUrl + email + "/" + digest.toString();

    http.Response response;
    try {
      response = await http.get(url);
    } on SocketException catch(e) {
      rethrow;
    }

    if(response != null && response.statusCode == 200) {
      return JsonEnvelop.fromJson(json.decode(response.body));
    } else {
      throw Exception('Failed to login');
    }
  }

void onVerifyCodeBtnPressed(BuildContext context) {
    if (_formKey.currentState.validate()) {
      String email = _emailController.text;
      String passwd = _passwdController.text;

      Future<JsonEnvelop> envelop;
      try {
        envelop = RemoteUserServices.loginUser(
            email, passwd);
      } on SocketException {
        throw Exception('Internet is down');
      }
      Scaffold.of(context).showSnackBar(SnackBar(content: Text('Login to your account')));

      envelop.then((JsonEnvelop envelop) {
        showDialog(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog(
              title: new Text("Login"),
              content: new Text("Login Successful"),
              actions: <Widget>[
                new FlatButton(
                  child: new Text("OK"),
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                )
              ],
            );
          }
        );
      });
    } else {
      showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            title: new Text("Missing data"),
            content: new Text("Type your email and password in the fields"),
            actions: <Widget>[
              new FlatButton(
                child: new Text("OK"),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              )
            ],
          );
        }
      );
    }
  }

What could be the problem in this situation? I hope to create a dialog box warning the user the internet is down.

like image 514
Marco Coelho Avatar asked Feb 28 '19 12:02

Marco Coelho


People also ask

What is exception handling error in Dart and flutter?

It is thrown when a schedule timeout happens while waiting for an async result. The main objective of the exception is to handle the run-time error and prevent the program from terminating abruptly. Every exception in the Dart is a subtype of the pre-defined class Exception.

How to catch exceptions in flutter?

How to Catch Exception In Flutter? If you want to find out the exact type of error you are getting, remove the exception so that all errors are caught, put a breakpoint within the catch, and check the type of error. so in this article, we will go through How to Catch Exception In Flutter How to Catch Exception In Flutter?

What happens if invokemethod throws an error in flutter?

If invokeMethod throws an error, it won’t be forwarded to FlutterError.onError . Instead, it’s forwarded to the Zone where runApp was run. To catch such an error, use runZonedGuarded.

How do you handle errors in flutter?

Errors that don’t occur within Flutter’s callbacks can’t be caught by the framework, but you can handle them by setting up a Zone. All errors caught by Flutter are routed to the FlutterError.onError handler. By default, this calls FlutterError.presentError , which dumps the error to the device logs.

What is the default error message in flutter?

By default, in debug mode this shows an error message in red, and in release mode this shows a gray background. When errors occur without a Flutter callback on the call stack, they are handled by the Zone where they occur. By default, a Zone only prints errors and does nothing else.


2 Answers

try/catch with exceptions from async code works only in functions with async, otherwise you'd need to pass onError callbacks or use .catchError(...) on the returned Future which is notably more difficult to get right.

  void onVerifyCodeBtnPressed(BuildContext context) async { // added async 
    if (_formKey.currentState.validate()) {
      String email = _emailController.text;
      String passwd = _passwdController.text;

      Future<JsonEnvelop> envelop;
      try {
        envelop = await RemoteUserServices.loginUser( // added `await`
            email, passwd);
      } on SocketException {
        throw Exception('Internet is down');
      }
like image 73
Günter Zöchbauer Avatar answered Nov 15 '22 10:11

Günter Zöchbauer


Instead of using rethrow or throwing a new exception. return a Future.error()

Future<bool> methodThatErrorsOnCall() {
 return Future.error();
}
...
...
methodThatErrorsOnCall.catchError((e) {
  print('I want to show a dialog: ${e.error}');     // callback fires.
  return false;                                     // Future completes with false
})
like image 39
Filled Stacks Avatar answered Nov 15 '22 10:11

Filled Stacks