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.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 4 of 4 of this article. Click here to view the first page.

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:

Home Page with friends and family members

Tap Save & Preview to see the information in the dialog:

Dialog without friends and family information

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:

  1. Checks whether _user object is null. Based on the result, it sets ListView‘s size either to the list size or to 0. You don’t need to check friendsAndFamily because it is not nullable. friendsAndFamily is always initialized when you create _user inside _displayUserInfo().
  2. Gets a person based on the index from friendsAndFamily and displays it in Text.

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:

Home Page

Tap the Save & Preview button to see the information in the dialog widget:

Dialog with all user information

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:

  1. Clears the inputs by assigning empty values to them.
  2. Resets _user to null. Pay attention to the null. 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.
  3. Clears the list of people from DataManager.

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:

Filled Dialog

Press Upload & Clear and you’ll see that the fields clear now:

Home Page with information cleared

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 is null.
  • If-null operator: ?? is shorthand for an if else condition. If the left side of the ?? operator is null, 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!