Blogi 22.4.2021

Flutter & sound null safety – Part 2: Collections

Kiva kun löysit tämän artikkelin! Se sisältää varmasti hyvää tietoa, mutta pidäthän mielessä, että se on kirjoitettu 3 vuotta sitten.

With the release of Dart 2.12 & Flutter 2, sound null safety is finally here! What are the benefits, and how do you migrate to null safety? It was all new for Jesper, who decided to read up on the subject and write a few blog posts (start with part 1) about what he learned.

Lists, Sets, and maps can both be non-nullable or nullable and contain non-null or null values.

Map behaves a bit differently than Lists and Sets, which is described in more detail below.

For a more detailed read, visit Google’s documentation:

List, Set

Here’s an informative image on Lists and Sets from Google docs, which is quite helpful:


List and Set examples:

List<String?> nullableValues = <String?>[’Kitchen’, ’Bedroom’, ’Bathroom’];

List<String?>? nullableListAndNullableValues = <String?>[’Kitchen’, ’Bedroom’, ’Bathroom’];

Set<String?> nullableValues = <String?>{‘Utensils’, ’Glasses’, ’Plates’};

Set<String?>? nullableSetAndNullableValues = <String?>{‘Utensils’, ’Glasses’, ’Plates’};


Here’s another informative image on Maps from Google docs, which is also quite helpful:

Map types have one special feature: a lookup may return a null value, as null is the value for a key which doesn’t exist in the map, and because of this, you can’t assign them to non-nullable variables.

A short example of this behaviour;

Map<String, int> categories = <String, int>{”Kitchen”: 1, ”Bedroom”: 2};

int value1 = categories[”Kitchen”]; // ERROR – value is non-nullable

The value variable has to be nullable in order for the lookup to work:

int? value2 = categories[”Kitchen”]; // OK

You can also use the ! operator if you’re sure the lookup succeeds:

int value3 = categories[”Kitchen”]!; // OK

A much safer option would be to use the ?? operator, as so:

Map<String, int> otherCategories = <String, int>{”Kitchen”: 1, ”Bedroom”: 2};

int value4 = otherCategories[”Kitchen”] ?? 0;

Required function parameters

One annoyingly behaving feature before Dart 2.12 is the @required keyword. You use it to annotate a specific parameter as required for a function, which takes optional parameters as well. Should the parameter be absent, then the application would throw some kind of error. The Dart analyzer will only warn you if you invoke that function without the required parameter instead of showing an error! This makes no sense, as you have explicitly indicated something as required. That should result in an error, not in a subtle warning.

With Dart 2.12, the parameters of a class constructor or function are required by default. And fortunately, @required has been replaced by required. The Dart analyzer will now show an error if a required parameter is absent, which is quite helpful especially in bigger codebases.

The three null safety principle

As Google puts it, Darts null safety support is based on three design principles:

  • Non-nullable by default. Unless you explicitly tell Dart that a variable can be null, it’s considered non-nullable. This default was chosen after research found that non-null was by far the most common choice in APIs.
  • Incrementally adoptable. You choose what to migrate to null safety, and when. You can migrate incrementally, mixing null-safe and non-null-safe code in the same project. We provide tools to help you with the migration.
  • Fully sound. Dart’s null safety is sound, which enables compiler optimizations. If the type system determines that something isn’t null, then that thing can never be null. Once you migrate your whole project and its dependencies to null safety, you reap the full benefits of soundness —- not only fewer bugs but smaller binaries and faster execution.

The first principle was explained in Part 1; you have to explicitly mark a variable nullable.

The second is something some of you might go for; mixing null-safe and non-null-safe code, nothing wrong with that. Third-party library developers have fortunately been quite active in migrating to null safety. That means that most of our favorite libraries are already null-safe at some capacity, and ready to be used in our next null-safe project.

The last principle is more practical, and what it’s all about; eliminating bugs, better performance, a more enjoyable developing experience, and so on. I strongly recommend that you opt into null safety in your next Flutter application.

In the last part, I’ll be covering migration to null safety. Thank you for reading!


Jesper Skand

Jesper has a great deal of experience in various mobile and full-stack developer roles. He has developed several different Flutter & Android apps and has currently three published apps on Google Play Store.
During his spare time, Jesper enjoys time with his kids, coding, and outdoor activities.

Takaisin ylös