Most people who’ve worked with Flutter have encountered null errors during runtime. They often look something like this:
These examples are just a few of the runtime errors from not initializing a variable in your application.
This is where Flutter’s null safety feature takes the center stage. Null safety is a guarantee within an object-oriented programming language that no object references will have
void values, especially during runtime.
Flutter’s null safety is bundled together with sound null safety to ensure that the Dart analyzer provides helpful warnings and tips.
To enjoy the benefits of null safety, you have to migrate your project to a null-safe version of Flutter 2, and this comes with a few changes. As always, the Dart documentation provides a good guide on how this migration works, and there is a handy command,
dart migrate, that helps automate the process, but this article will walk you through the step-by-step process involved in migrating an old project to null safety.
Here is what you need to take into consideration before migrating your project to a null-safe version.
Check whether your project uses null safety
In order to know if your project is using null safety or not, go to your
pubspec.yaml file and check under the environment section for the Dart SDK version currently in use by your project:
environment: sdk: ">=2.10.0 <3.0.0"
If your SDK version on the left is equal to or less than 2.10.0, then you currently do not have null safety enabled in your project.
On the other hand, if your version number is 2.12.0 or higher, then you have null safety enabled in your project.
Migrate your packages
For this article, we will be migrating my Sleek Note App project to null safety, and this would be done on a new branch off the master branch on GitHub:
dart pub outdated --mode=null-safety
We are going to use the command above to check the status of the packages that we use in our project and see if they can be migrated to a null-safe version.
Our project contains the following packages:
In our case, this is the result we get from running the command:
The result shows that all our packages can be upgraded because they all have newer versions that support null safety under the Resolvable and Latest columns. If for any reason the package you use does not have a null-safe version or prerelease, you can always reach out to the author from the package website.
In order to migrate our packages, we are going to use the command below:
dart pub upgrade --null-safety
Upon completion, run the following command:
flutter pub get
Once we’re done with the above, our updated packages in our
pubspec now look something like this:
After determining that you are not running null safety in your project and you would like to make the switch, the next step is making sure that all the packages you use have been properly migrated to null safety.
This also implies that if you use a package with a chain of dependency on another package, you would need to wait for the packages to be migrated in order of their hierarchy. For instance, if your project uses package A and depends on package B, which in turn depends on package C, the first package to be migrated should be C, followed by B and then A.
N.B., it is possible to migrate your packages to null safety before the packages that depend on them are migrated, but this step ensures that you do not encounter bugs when those packages are finally migrated.
Migrate your Flutter project
We are going to migrate our code using the Dart migration tool. If you are comfortable with the Dart null safety syntax, you can also migrate your code manually.
Using the Dart migration tool
To use the Dart inbuilt migration tool, run the following command:
Since we completed the steps above, we are going to be presented with a link, and this link should be opened in a Chrome browser.
When our browser window opens up, we are going to see all our project files selected, and you can walk through each project file to see the changes made. In our case, if you take a look at our
Note Model class, you will find that one of the major changes is that a non-null assertion will be added to all nullable expressions.
It is important to note that for most of your production-scale applications, especially larger projects with lots of files, you might not want to migrate everything at once. So you can simply uncheck your files and project folders and use what is called incremental migration. You can find out more details about incremental migration here.
For this particular project, we are going to apply the changes to all of our files by clicking on Apply Migration, since everything looks good to go.
After doing this, we can get our package by running the
flutter pub get command and try to run our project.
We seamlessly succeeded in migrating an older project to null safety.
Manually migrate your code to null safety
Check your Dart version using the code below to ensure you are not running any version less than Dart 2.12:
If you are, simply update the number in your
pubspec.yaml file to look like this:
environment: sdk: ">=2.12.0 <3.0.0"
This is also a cool way to disable null safety from your project.
Any time you need to turn off null safety, simply downgrade your version number and run
flutter pub get to update your dependencies again.
After doing that, update your packages again using the command below:
dart pub get
As expected, the analyzer will frown at your code and point out lots of analysis errors, and you will have to make changes where necessary. Most of the changes required would simply be adding
! required, and
late where they are needed.
Upon completion, you can run the code below to verify the changes you made:
From the foregoing, we can see how useful sound null safety can be.
Remember to always make use of the null aware operator
? with variable types or named parameters that you need to declare null aware to reduce compile-time errors.
You can always refer to the official docs on null safety for more information.
LogRocket: Full visibility into your web apps
LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.