Non-Nullable Dart: Understanding Null Safety
Learn how to use null safety in Dart. Get to know Dart’s type system and how to utilize language features in production code. By Sardor Islomov.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Non-Nullable Dart: Understanding Null Safety
30 mins
- Getting Started
- Getting to Know the App
- Understanding Sound Null Safety
- Exploring the Dart Type System
- Enabling Null Safety
- Migrating to Null-Safe Dart
- Creating Model Classes
- Reviewing the Person Class
- Creating the User Class
- Creating Friend and FamilyMember Classes With Nullable Types
- Declaring Nullable Types
- Creating FamilyMember With a Nullable Property
- Using Late Variables and Lazy Initialization
- Retrieving Data From Widgets
- Understanding the Never Type
- Understanding Flow Analysis
- Testing the Never Type
- Using Type Promotion
- Displaying Member Names on the Home Screen
- Displaying User Details in the Dialog
- Retrieving User Input From the TextFields
- Displaying the Dialog With the User Information
- Displaying the User Relationship
- Clearing the UI
- Sound Null Safety In a Nutshell
- Where to Go From Here?
Displaying the Dialog With the User Information
You need to display the user’s provided information in the corresponding UserTextWidget
widgets in _showPreview()
.
First, fix the user’s name:
UserTextWidget('${ProjectConst.NAME}:${_user?.name}'),
Here, you access the name of the user using Dart’s null-aware operator, ?.
. You use that operator because you declared _user
as a nullable field, implying the field can be null
. Without the null-aware operator, the program could crash if _user
is null
. In this case, it will return null
.
Notice that you didn’t use the bang (!
) operator because, even when _user
is null
, the bang operator will try to forcefully cast it to a non-nullable _user
type, which will result in an error.
Next, fix the other widgets in _showPreview()
with their respective user details:
...
UserTextWidget('${ProjectConst.SURNAME}:${_user?.surname}'),
UserTextWidget('${ProjectConst.GENDER}:${_user?.gender.toString()}'),
UserTextWidget('${ProjectConst.BIRTH_DATE_LABEL}:${_user?.birthDate}'),
Build and run, then enter information about the user:
Tap Save & Preview to see the information in the dialog:
You’ve set up everything except the user relationship. You’ll do that next.
Displaying the User Relationship
To display friends and family members, you need to modify the ListView
in _showPreview()
. Make sure the ListView
looks like this:
ListView.builder(
padding: const EdgeInsets.all(ProjectConst.value8),
// 1
itemCount: _user?.friendsAndFamily.length ?? 0,
itemBuilder: (BuildContext context, int index) {
//2
final person = _user!.friendsAndFamily[index];
return Center(child: Text('${person.name} is ${person.whoAmI}'));
})
This is how ListView
implements the friends and family members:
- Checks whether
_user
object isnull
. Based on the result, it setsListView
‘s size either to the list size or to 0. You don’t need to checkfriendsAndFamily
because it is not nullable.friendsAndFamily
is always initialized when you create_user
inside_displayUserInfo()
. - Gets a
person
based on the index fromfriendsAndFamily
and displays it inText
.
At this point, you’ll see a preview dialog containing all the information about the user.
Build and run, then enter the user’s information:
Tap the Save & Preview button to see the information in the dialog widget:
Clearing the UI
If the user taps the Upload & Clear button, the dialog disappears but the input fields do not. To clear them, implement a new _clearUI()
:
void _clearUI(){
setState(() {
//1
_nameController.text = '';
_surnameController.text = '';
_birthDateController.text = '';
_familyMemberNames = '';
_friendNames = '';
_dropdownValue = ProjectConst.FEMALE;
_genderImage = ProjectConst.FEMALE_IMAGE;
//2
_user = null;
//3
DataManager.people.clear();
});
}
Essentially, this code:
- Clears the inputs by assigning empty values to them.
- Resets
_user
tonull
. Pay attention to thenull
. Remember, all code by default is safe. If you’d created a non-nullable_user
like this:User _user
, then you wouldn’t be able to assign a null to it. - Clears the list of
people
fromDataManager
.
Now, call _clearUI()
inside _onClearClicked()
. This method triggers when the user clicks the Upload & Clear button.
void _onClearClicked() {
_clearUI();
Navigator.pop(context);
}
This clears the user input and closes the dialog.
Build and run, then enter a user’s information:
Press Upload & Clear and you’ll see that the fields clear now:
Congratulations, you finished ProfileApp! Best of all, it’s null-safe. Even if some NullPointer errors come up, your app can handle them.
Sound Null Safety In a Nutshell
Dart has three main operators to work with null
:
-
Null-aware operators: The null aware accessor
?.
, which accesses properties of its operand, is an example. If the operand is null, then it will not throw an exception. Instead, it shows null text. -
Bang operator: Use (
!
) to cast away nullability. It tries to cast a nullable type to a non-nullable type, throwing an exception if the operand isnull
. -
If-null operator:
??
is shorthand for anif else
condition. If the left side of the??
operator isnull
, then it will use its right side.
Where to Go From Here?
Download the completed project files by clicking the Download Materials button at the top or bottom of the tutorial.
In this non-nullable Dart tutorial, you learned:
- How to write null-safe code for a new or an existing Flutter project.
- The Dart type system.
- Nullable types and how to declare them.
- Type promotions.
- Abstract types and how Dart treats them.
You can expand your knowledge about null safety in Dart further by reading Dart’s Understanding Null Safety documentation.
If you’d like to learn more about Flutter, check out our Flutter video courses and articles.
We hope you enjoyed this tutorial. If you have any questions or comments, please join the forum discussion below!