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.
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 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?
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.
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.
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.
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');
}
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
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With