Showing Custom Flutter Red Screen Error
--
Every flutter developer comes across this famous error screen, quite often, during their initial stages. While this seems to be most irritating when you are a beginner, but yet, this is one of the most highlighting feature provided by Flutter which remarkably differentiates it from other developing tools in the market atleast native Android developement.
As per the docs, Flutter generates red screen error whenever a widget fails to build. If you take a peek into StatefulWidget.dart class, you will see this code being invoken in performRebuild() method:
@override
void performRebuild() { //..//
try {
built = build();
debugWidgetBuilderValue(widget, built);
} catch (e, stack) {
built = ErrorWidget.builder(_debugReportException('building $this', e, stack));
} //..//
}
In this you can see this Red Screen Error is nothing but a widget named ErrorWidget provided by framework.
Note that this ErrorWidget will be invoked only when a widget building fails, so that ErrorWidget replaces it when an error occurs in build method of that widget. That’s why its visible only in the area occupied by the widget that has failed to built.
What if you want to display this red screen error without being depended on ‘widget building fails’ condition?
For eg, you are having a list of strings like this:
List<String> _list = ["Flutter", "Android", "iOS"];
What if you want to test it for null value and want to show a red screen error ? Well you can use ‘assert’ :
assert(_list!=null,"List is null");
But this statement will not show a red screen error if a widget hasn’t got affected by the list null value. ‘assert’ in this case simply logs the message onto the console.
What if we want a red screen instead?
For achieving this let’s make a new Flutter project named flutter_red_screen_error.
Here we have simply three files:
In home_page i have a button which simply shows the first page and a list is passed from home_page to first page:
What if the list passed to first page is null? You might then throw an exception ,as a check, for this:
void _showSecondPage() {
if (_list != null)
Navigator.of(context).push(MaterialPageRoute(builder: (context)
=> FirstPage(_list)));
else
throw new Exception("List passed to first page is
null!")
}
But this will again logs the error to console(as no widget is affected by it) making the developer to look for the cause through console only, which in my view is a little tiring business.
If that would have been displayed as as red screen error, then it would have been useful for both the developer and tester.
Hence, Let’s show this error as red screen error
Here we will be replacing the root widget of our app with ErrorWidget when an error occurs so as to display a red screen error.
To achieve this, you have to first attach a global key in root widget of your app, ie MyApp in our case, in order to get access to the state of our root widget.
GlobalKey<MyAppState> rootKey = new GlobalKey();
void main() => runApp(
MyApp(key: rootKey),
);
Now define a method showError which accepts a message string as parameter. Call setState() to set the _errorMessage field and add a condition to build() method to show ErrorWidget when _errorMessage is not null.
After implementing, our main.dart looks something like this:
import 'package:flutter/material.dart';
import 'package:flutter_red_screen_error/home_page.dart';
GlobalKey<MyAppState> rootKey = new GlobalKey();
void main() => runApp(
MyApp(key: rootKey),
);
class MyApp extends StatefulWidget {
MyApp({Key key}) : super(key: key);
@override
MyAppState createState() {
return new MyAppState();
}
}
class MyAppState extends State<MyApp> {
String _errorMessage;
onError(String message) {
if (mounted)
setState(() {
_errorMessage = message;
});
}
@override
Widget build(BuildContext context) {
return _errorMessage != null
? ErrorWidget(_errorMessage)
: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.red,
),
home: HomePage(),
);
}
}
Explanation: Here if _errorMessage is null ErrorWidget is returned else MaterialApp will be returned.
Access the global key that we defined anywhere in your app and call the onError() method like this:
rootKey.currentState.onError("Your error message");
Now, If you now pass a null list to the first_page like this:
void _showSecondPage() {
_list=null; //We make the list null now for checking if (_list != null)
Navigator.of(context).push(MaterialPageRoute(builder: (context) => FirstPage(_list)));
else
rootKey.currentState.onError("List passed to first page is null!");
}
The result would now look to what’s the article is all about:
Yay 🤩! We successfully showed a red screen when the list passed was null to our first page. You really did a good job for yourself and your tester. No more hassle in bug reporting.😊
Whola! Both you and I learnt something new today. Congrats
Clap! Clap! Clap! 👏👏👏
The full source code of this sample is available here.
Further Reading:
- https://docs.flutter.io/flutter/widgets/StatefulWidget-class.html
- https://docs.flutter.io/flutter/widgets/ErrorWidget-class.html
Read my other blogs on Flutter:
- https://medium.com/flutterpub/flutter-listview-gridview-inside-scrollview-68b722ae89d4
- https://medium.com/flutterpub/validating-json-in-flutter-6f07ec9344f8
- https://medium.com/flutterpub/flutter-andorid-keystore-path-on-different-os-d0fc30a24d4f
- https://medium.com/@ayushpguptaapg/demystifying-and-hashcode-in-dart-2f328d1ab1bc
The Flutter Pub is a medium publication to bring you the latest and amazing resources such as articles, videos, codes, podcasts etc. about this great technology to teach you how to build beautiful apps with it. You can find us on Facebook, Twitter, and Medium or learn more about us here. We’d love to connect! And if you are a writer interested in writing for us, then you can do so through these guidelines.