Sound Null Safety: make better apps with Flutter!

Subscribe to my newsletter and never miss my upcoming articles

Hi everyone in this article I want to dive deeper into one of the recent announcements made in the Flutter Engage Event: Sound Null Safety. Any of you who have programmed at least once in your life will surely have encountered an error or exception related to a NULL variable. These errors are often difficult to debug because they occur only during the execution of a program and are difficult to predict during development.

To solve this problem the team of Flutter and Dart have introduced the concept of Sound Null Safety which means that types in your code are non-nullable by default and null-dereference errors are no longer "discovered" at runtime but during code writing and this makes your code more secure and less prone to errors at runtime. To better understand how to take advantage of this functionality, let's first introduce some concepts, and then we will move on to the best practices and tools that Flutter provides to make our life easier to make our applications perform better.


The first thing to keep in mind is that types are non-nullable by default unless you explicitly tell Dart that a variable can be null. If you tell Dart that a variable isn’t null, then that thing can NEVER be null and the compiler can make optimizations on your code (because it no longer has to check every time it is used that it is not NULL or "hope" that it is not) and benefits are fewer bugs, smaller binaries, and faster execution. Another important benefit is that you can incrementally migrate your code to null safety, you can mixing null-safe and non-null-safe code in the same project so you can test each part of your app separately until you reach the full migration to null safety.

Now I introduce you to three syntactic operators that help us write safer code or tell the compiler how it should handle a variable: ? ! and late.

The ? operator tells Dart that a variable can have a null value and it doesn’t have to worry because, as good programmers, we add all the code necessary to verify, when we have to use it, that that value is not null

//I declare and assign a variable that can be null
int? iKnowThisVariableWillNoLongerBeNull = null;

* Some code that maybe assign a non-null value

//Check if the variable is not null
if( iKnowThisVariableWillNoLongerBeNull == null ){

//I can use iKnowThisVariableWillNoLongerBeNull 
//    because is not null and I'm a good programmer ;-)
//    so I don't have a runtime error

The ! operator overrides what Dart compiler thinks of a variable because if you are 100% sure that a variable will be not null until it's used and the compiler doesn't have to worry about its value you can add the ! operator

//Now I declare and assign a variable that can be null
String? firstVariable = "Alberto";

* Some code

//I'm 100% sure that my variable is not null 
//    because I assign its value when I declare it
//    and I override what Dart thinks
String myName = firstVariable!;

Another way to tell Dart that a non-nullable variable will be initialized to a non-null value before it’s used is with the late keyword

int randomNumber(){
    //I define a "maybe" null variable but I tell Dart 
    //    that somewhere in my code I will assign 
    //    a non-null value
    late int randomNumber;
    int returnedRandomNumber;

    //I have fulfilled my promise to assign 
    //    a non-null value to the variable
    randomNumber = 4;
    returnedRandomNumber = randomNumber;

    return returnedRandomNumber;
print(randomNumber()); //This string prints the random number 4

Tips & Tools

If you want to migrate your app to null safety the Flutter team provides you some useful tools to make this migration easy. First of all, check that you have Dart 2.12 or later installed with Flutter > 2.x.x, you can check it with

$ dart --version

Dart SDK version: 2.12.0 (stable) (Thu Feb 25 19:50:53 2021 +0100) on "linux_x64"

After that, you have to keep in mind that before migrating your actual code you should wait until all packages your app depends on have been migrated to null safety, to check it run

dart pub outdated --mode=null-safety

This is a simple output and if in the Resolvable column all the packages have a green checkmarked version all of your dependencies are already migrated to null safety and you can upgrade


If any of your package’s dependencies don’t yet support null safety, you can reach out to the package owner and tell if a null-safety release of the package is in work and you can help with something. If all is green you can upgrade all of your dependencies, and update the pubspec.yaml file, with

$ dart pub upgrade --null-safety
$ dart pub get

The last step is to migrate your actual code with

$ dart migrate

If all it's ok and your app is ready to migrate, then you should see an output like this

View the migration suggestions by visiting:

Going in that webpage you will see what changes Dart proposes for your code and you can apply all the changes in one shot, apply changes only to certain parts of your app, or review them and apply by hand. The Flutter team suggests applying changes only to one part of your app at a time and test them until you reach the full migration.

If you start from scratch with a brand new app and you want to have null safety from day 0 you have to create your project with

 $ dart create -t console-full my_brand_new_app
 $ cd my_brand_new_app
 $ dart migrate --apply-changes


I think that Sound Null Safety is a wonderful addition to Dart and Flutter because it forces us to think more about our code and to write it better, it makes our apps faster and with fewer bugs. If you want to experiment with Null Safety in Dart before diving in to introduce it in your apps you can use the DartPad with null safety.

Bye, Alberto

No Comments Yet