Getting Started
Setup Dependencies¶
Add the runtime dependency flutter-errors
to your pubspec.yaml
.
flutter-errors
holds all the code you are going to use in your application.
dependencies:
flutter:
sdk: flutter
flutter-errors: ^1.0.0
Features¶
ExceptionMappers
singleton object, storage that stores a set of exception converters to error classes required forErrorPresenter
objects.ExceptionHandler
implements safe code execution and automatic exception display usingErrorPresenter
.ErrorPresenter
classes implements a strategy for displaying exceptions in a user-friendly form on the platforms. Converts the exception class to an error object to display.
There are several ErrorPresenter
implementations:
AlertErrorPresenter
- displays errors text in alert dialogs.ToastErrorPresenter
- displays errors text in toastsSnackBarErrorPresenter
- displays errors text in snackbar.SelectorErrorPresenter
- for selecting error presenter by some custom condition.
Usage¶
ExceptionMappers¶
Register a simple custom exceptions mapper in the singleton storage:
ExceptionMappers.instance
.register<NetworkError, String>( // Will map all NetworkError instances to String
(e) => "NetworkError registered error")
.register<HttpException, String>( // Will map all HttpException instances to String
(e) => "Format Exception registered error");
Registration of custom exception mapper with condition:
ExceptionMappers.instance
.condition<NetworkError>( // Registers exception mapper Exception -> String
(e) => e is NetworkError && e.error.code == 1, // Condition that maps Exception -> Boolean
(e) => "My Custom Error from mapper"); // Mapper for Exception that matches to the condition
For every error type you should to set fallback (default) value using method setFallbackValue
ExceptionMappers.instance
.setFallbackValue<Int>(250); // Sets for Int error type default value as 250
// Creates new mapper that for any unregistered exception will return the fallback value - 250
val throwableToStringMapper: (Exception) -> String = ExceptionMappers.instance.throwableMapper()
Using factory method throwableMapper
you can create exception mappers automaticlly:
String Function(Exception) throwableToIntMapper = ExceptionMappers.throwableMapper();
If a default value is not found when creating a mapper using factory method throwableMapper
, an exception will be thrown FallbackValueNotFoundException
The registration can be done in the form of an endless chain:
ExceptionMappers.instance
.condition<String>(
(e) => e is NetworkError && e.error.code == 1,
(e) => "My custom error from mapper")
.register<NetworkError, String>(
(e) => "NetworkError registered error")
.register<FormatException, String>(
(e) => "Format Exception registered error")
.register<HttpException, Int>(
(e) => e.error.code,)
.setFallbackValue<Int>(250);
ExceptionHandler¶
- Declare
ExceptionHandler
property in someViewModel
class:
class SimpleViewModel extends ViewModel {
final FlutterExceptionHandlerBinder exceptionHandler;
SimpleViewModel(this.exceptionHandler,)
// ...
}
- Bind
ExceptionHandler
in the platform code.
On Base page or Page State register WidgetsBindingObserver
& FlutterWidgetBindingObserver
class Page extends State with WidgetsBindingObserver{
final FlutterWidgetBindingObserver stateObserver =
FlutterWidgetBindingObserverImpl();
@override
void initState() {
WidgetsBinding.instance.addObserver(this);
super.initState();
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
stateObserver.didChangeAppLifecycleState(state);
super.didChangeAppLifecycleState(state);
}
}
initState
of StatefulWidget
or onModel
ready of viewmodel
bind the observer:
viewModel.exceptionHandler.bind(
super.stateObserver
);
ExceptionHandler
class which uses (Exception) -> String
mappers:
FlutterExceptionHandlerBinderImpl<String>(
ExceptionMappers.instance.throwableMapper(), // Create mapper (Exception) -> String from ExceptionMappers
errorsPresenterInstance, // Concrete ErrorPresenter implementation
FlutterEventsDispatcher(),
(e){ // Optional global catcher
println("Got exception: $e"); // E.g. here we can log all exceptions that are handled by ExceptionHandler
}
);
ViewModel
:
void onMakeRequest() {
exceptionHandlerBinder.handle(block: (){
serverRequest(); // Some dangerous code that can throw an exception
}).finallyIt(block: (){ // Optional finally block
// Some code
}).execute(); // Starts code execution
}
- Also you can add some custom
catch
handlers forExceptionHandler
that work as a catch in the try/catch operator:
void onMakeRequest() {
exceptionHandlerBinder.handle(block: (){
serverRequest(); // Some dangerous code that can throw an exception
}).catchIt<FormatException>((FormatException e){ // Specifying exception class
// Some custom handler code
return false; // true - cancels ErrorPresenter; false - allows execution of ErrorsPresenter
}).execute(); // Starts code execution
}
ErrorPresenter¶
There are ErrorPresenter
interface implementations:
* AlertErrorPresenter
- displays errors text in alert dialogs;
* ToastErrorPresenter
- displays errors text in toasts;
* SnackBarErrorPresenter
- displays errors text in snackbar;
* SelectorErrorPresenter
- for selecting error presenter by some custom condition.
You need to pass some ErrorPresenter
to ErrorHandler
instance. E.g. creation of error presenters
in common code:
...
Samples¶
Please see more examples in the sample directory.