DEV Community

Olamide Gabriel
Olamide Gabriel

Posted on

Simplifying Null Safety in Flutter

INTRODUCTION

Have you ever run into the red screen of horror while debugging a flutter app?

null.jpg

I mean, if you haven’t, are you a Flutter developer at all?

Out of numerous reasons for your app to relay your error in such a manner, null errors are one of the most common. In an attempt to eliminate this and the numerous null errors that occur while building/debugging your app, the great Flutter and Dart team introduced Null Safety.

In simple terms, Null Safety allows the dart analyser to detect possible null errors pre-compilation, that is, before you even run your app. It ensures proper notifications of possible null data that could break your app while running.

This article is for you, if

  1. You understand the basics of data types in Dart.
  2. You know a bit about classes, objects, i.e. the basics of OOP in Dart.

Else, you might want to go through the Dart documentation.

First, we will discuss the syntax changes and what they mean with the introduction of Null Safety.

You may have seen characters such as "?", "!", and "??", and keywords such as "late".They are the main code additions you are required to understand.

For the dart analyser to help you convert your runtime errors to "code time" errors, it needs some information. Before Null Safety, all variables were particularly nullable, so developers may forget to check if these variables are null, causing the red screen of death during debugging quite often or crash during production in the worst-case scenario. The analyser needs to know what variables might be null or will never be null.

Before Null Safety, you would create a variable like this:

///BEFORE
int myFavoriteNumber = 5;
//OR
int myFavoriteNumber;
Enter fullscreen mode Exit fullscreen mode

In the first instance, we assigned myFavoriteNumber a value of 5. Although, along the line, we could assign it a value of null by writing

myFavoriteNumber = null;

And in the second instance, myFavoriteNumber was null from the start.

However, with Null Safety present, the rules have changed.

#Instance 1
int favoriteNonNull = 7;
# Instance 2
int? favoriteNullable;
#Instance 3
int? favoriteNullabe2 = 10;
Enter fullscreen mode Exit fullscreen mode

Instance 1: We created a non-nullable variable and assigned it a value of 7. What does this mean? We have simply told the dart analyser that this variable can and must NEVER be null. It means you must assign it a value at the point of creation, and you could NEVER assign it a null value in the future. Going against any of these would force the dart analyser to scream in your face.

Instance 2&3: We added a "?" right in front of the data type. It tells the analyser that "favoriteNullable" can be null. Thus, in cases where a non-nullable variable is required, the dart analyser should remind us to do a null check. You can mess with this variable and assign it a null value. The analyser is your guide.

How do you perform null checks?

While writing Dart, which is an OOP language, you might find yourself using objects a lot with attributes/properties that may have null values. Your objects could be null as well as variables. Not to worry, "?" and "??" help with this issue.

Let us examine a simple class "Dog" with attributes "name", "colour", and "weight".

class Dog{
String? name;
String? colorName;
int? weight;
Dog({this.name,this.colorName,this.weight});
}

Dog? nullableDog;
Dog? nullableDog2 = Dog(
name :  "Jack",
colorName:  "Brown",
weight : 20,
);
Dog nonNullableDog = Dog(
name :  "Finn",
weight : 18,
);
#Extra variable for demo purposes
int? demoVariable = 30;
Enter fullscreen mode Exit fullscreen mode

The easiest and most common way to perform a null check is using an if statement.

if(variable != null){
//use variable
}
Enter fullscreen mode Exit fullscreen mode

However, we want to explore how the characters mentioned above can help us instead.
For instance, say you're to use a nullable String in a Text widget which would not take nullable strings as a parameter. "??" comes in handy as you can use it to perform a quick null check and provide an alternative for the widget, thereby preventing possible crashes.

String? parameter;
//Some Widget Tree
...
Text(
parameter ?? "Alternative Text",
)
...
//Some Widget Tree
Enter fullscreen mode Exit fullscreen mode

Note: The dart analyser won't be too happy about an absence of a null check and alternative in this scenario.

What if we wanted the name of our "nullableDog2" created above?

Recall that "nullableDog2" is a nullable object with the nullable attribute "name". Did that confuse you? It simply means our "nullableDog2" may be null, and even if it isn't, its attribute name may be null as well. If we use this value in our Text widget, we would need to perform some extra checks. "?" allows you to perform a quick null check on an object while accessing its attributes. It saves you a couple of lines of code and makes objects easier to use within widgets.

Here’s a brief demonstration:

//Some Widget Tree
...
Text(
nullableDog2?.name ?? "Alternative Text",
)
...
//Some Widget Tree
Enter fullscreen mode Exit fullscreen mode

The dart analyser isn't perfect and sometimes would not realise some things a developer would. For example, you might be 100% sure a variable you have created to be nullable would not be null at the point you wish to use it. You want to shut the analyser up and tell it you know better. That's fine, but it comes with the risk of crashing your app. You need to be 100% sure. Dart has provided "!" to help silence the edit time warnings.

A quick demo

String? parameter;

//Written some magic somewhere to make sure "parameter" isn't null when I need it...
//Some Widget Tree
...
Text(
parameter!,
)
...
//Some Widget Tree
Enter fullscreen mode Exit fullscreen mode

OR

String? parameter;

//Some Widget Tree
...
if(parameter != null) //the analyzer may not detect this check
Text(
parameter!,
)
...
//Some Widget Tree
Enter fullscreen mode Exit fullscreen mode

Finally, let's talk about the late keyword. Referencing the meaning of the word “late”, which means "not on time", by using this keyword, you are simply telling Dart that your variable is not going to be null, but you are not going to assign a value immediately it's created. You're going to assign it a value a little bit later before it is used.
This is useful for variables that are expensive to create.
Note: Failure to assign a value to late variables would cause your app to crash/errors during debugging.

//Inside some stateful widget
...
late AnimationController controller;
@override
initState(){
super.initState();
controller = AnimationController(
vsync:this,
);
}
Enter fullscreen mode Exit fullscreen mode

We have covered the basics of null safety and the keywords you would mainly be dealing with. I hope this will help you prevent more null errors in the future!

For more examples and active practice, check out intro to null safety by the Dart team.

If this was useful for you, be sure to leave a like and comment, and please share. Thank you!

Top comments (1)

Collapse
 
vineyrawat profile image
Viney Rawat

Good 👍