Benefits of Null safety in Flutter 2

Photo by Artur Shamsutdinov on Unsplash

In July 2020, sound null safety was introduced to the Dart programming language. As this language powers Flutter SDK, the support for null safety was one of the anticipated improvements coming with Flutter 2.

The release of the new Flutter version on March 3, 2021, finally made it possible not only to write new code using the null safety feature but also to migrate the existing Flutter apps to null safety. The updates and new releases didn't end, with the latest version released in May, 2023.

Let’s consider how null safety is implemented in Flutter, how it influences the development process, and what benefits it brings.

What is sound null safety?

Let’s step back in history. Null pointer or null reference was invented by Tom Hoare in 1965. Later, in 2009, he would call it a billion-dollar mistake during his speech at a development conference.

Tom Hoare was designing the first comprehensive type system for object-oriented programming (OOP). To make sure that the use of all references is safe, he decided to implement the null pointer reference as the easiest solution. As a result, the null error was born.

Sound null safety eliminates bugs caused by null pointers. It makes types in your Dart code non-nullable by default. It means that variables can’t contain null unless you say they can.

The problems null pointers used to cause

The problem is that null didn’t represent any valid objects but also didn’t generate errors during compilation. Being a type-safe language, Dart had tools to automatically check if all variables used in a piece of code belonged to the correct types. But it didn’t have tools to check if the variable was not null. Null errors used to be very common and difficult to spot.

For example, database access or API calls are usually very prone to null errors. If a database row didn’t exist, you might have got a null. Developers had to handle such cases during development otherwise they would cause undefined behavior in the application during runtime. That would result either in a small bug or a complete crash.

Adding null safety to Dart and Flutter became a good solution to developer productivity issues and reduced the number of bugs. With null safety, now Flutter developers can specify which variables can be null and all the previously unnoticed errors will show up during static analysis. It means that all issues can be noticed and fixed fast during edit time.

Null safety and first implementation in Dart

The syntax of null safety in Dart is very similar to other languages. It uses the “?” symbol and also "!" and the "late" keyword. You can try the things out in the null-safety-enabled Dart pad.

Here’s a quick example. A dynamically typed variable declared like this will never be null:

var i = 42;

Nor can be any of the declarations with static types.

String hello = “world”;

If we want to specify that a variable can be null, we use a “?”. In this case, if we ever reassign it to null, it’ll be valid.

String? hello = “hello”;
hello = null;

This is an easy way to understand null safety in Dart for now.

There are many other things to it. Null errors usually come from side effects. A side effect is like a “quality” of a function. This means the function will access or modify a variable outside its scope or local environment.

For example, accessing a database from a function will return values from the database which exists outside the function. The effect is the return of the function and the side effect is that database access inside.

Many times when you want to access the result of a side effect inside a function you’ll reassign a variable. Look at this example:

int? dbcall(bool condition){
    return 1;
  } else {
    return null;

This can return null in case the condition is false.

  int? queryResult = dbcall(false);

With null safety, this assigned statement will be an edit time error if we don’t add the question mark.

A less boring feature that comes with null safety is the “late” keyword used for lazy initialization. The variables here are initialized only when they are used. “Lazy” is the opposite of “eager” and it can allow some pretty cool optimization implementations.

The use of “late” is pretty simple and going to be quite common, I think. Here is a super simple example:

class A{
    late int a;

    //... other stuff

With null safety checks, we cannot have variables uninitialized inside a class. Even if we set it inside the constructor, we cannot have those anymore without the “late” keyword. If you remove it, it’ll result in an error.

It seems it’s similar in use to the “?” but this is used for slightly different scenarios because late works with lazy initialization while “?” doesn’t.

Null safety improvements to Flutter

Null safety speeds up the app development time. Moreover, code maintenance becomes easier with it because developers can spend fewer hours looking for errors caused by null that used to come out during runtime. The whole developer team becomes more productive and can focus on more important things.

As a best practice, developers should strive to remove all nulls from the code. However, if using nulls is unavoidable, it’s possible now to instantly notice and handle it.

Reasons to migrate a Flutter app to null safety

There are many reasons to migrate Flutter apps to null safety, like those mentioned above, and it’s a must-do. This feature is a breaking change and previously written apps will not compile with the null checker on which might tempt some lazy developers to not activate it.

You should know that when doing refactoring for null safety you can completely rely on the compiler. It makes the process quite simple. I believe that migrating your code to null safety is rather mandatory than optional. The efforts you devote to this will save you many hours of work afterwards.

Sound null safety is a great feature that allows Dart to catch up with other languages like Kotlin and TypeScript. It reaffirms that Dart is a developer happiness-focused language. It was about time the Flutter development team gave us this feature and it’ll just make Flutter SDK even better for writing apps that run literally everywhere.

QA for Flutter null safety

You ask, we answer.

What is sound null safety?

Sound null safety makes types in code non-nullable by default and enables special static checks and compiler optimizations to guarantee that null-dereference errors won’t appear at runtime because they will be spotted at compile-time and fixed. Soundness means that you can trust the type system when it determines that something isn’t null because it can never make a mistake. You can achieve soundness only if all libraries you use in the engagement have null-safe code.

What is null safety in Flutter?

Flutter null safety is the feature that became available after the release of version 2 where the minimum version of Dart programming language is set to 2.12. This feature helps to improve developers’ productivity by eliminating a whole class of bugs caused by null dereferencing errors. And, the latest version of Flutter is 3.10, released in May, 2023.

How to migrate to null safety Flutter 2?

First, you should check if all the code packages your code depends on had migrated to null safety to make sure you’re ready to migrate. Then, update to Flutter 2 and make sure you use Dart 2.12 or later. Migrate your code using the interactive migration tool built by the Dart team or by hand. Afterwards, run tests to make sure your app works as intended. You can migrate all files of your app or only part of them. Mind that once you have a file migrated to null safety you can’t un-migrate it.

How do I turn off null safety Flutter?

You can run your Flutter 2 app without sound null safety if your app has a mixed-version code or has dependencies on code packages that haven’t migrated yet. For this, you can disable the sound null safety feature by --no-sound-null-safety flag to the Dart or Flutter command or by setting the Dart language version in the entry point to 2.9.

Find your next developer within days, not months

We can help you deliver your product faster with an experienced remote developer. All from €31.90/hour. Only pay if you’re happy with your first week.

In a short 25-minute call, we would like to:

  • Understand your development needs
  • Explain our process to match you with qualified, vetted developers from our network
  • Share next steps to finding the right match, often within less than a week

Not sure where to start?

Let’s have a chat

First developer starts within days. No aggressive sales pitch.