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 null
or 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.
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.
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.
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.
To use the Dart inbuilt migration tool, run the following command:
dart migrate
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.
Check your Dart version using the code below to ensure you are not running any version less than Dart 2.12:
dart --version
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:
dart analyze
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.
The null-safe version of our project can be found here.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to implement one-way and two-way data binding in Vue.js, using v-model and advanced techniques like defineModel for better apps.
Compare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.