skip to Main Content

i have a model it looks like this

 class UserModel {
  final String? username;
  final int? age;
  final String? phoneNumber;

  UserModel(
      {required this.age, required this.phoneNumber, required this.username});

  @override
  String toString() {
    return 'Username => $usernamenAge => $agenPhone number => $phoneNumber';
  }
}

what im confusing for now is what is better to use with ? or without ? like final String? username or final String username

and if some how the data i get from server username is null how do i handle it ? i want to keep the ui code clean as possible so i dont want to put if(user.username == null) in the ui i want to keep it in the model or controller how ?

2

Answers


  1. In Dart, the use of ? after a type (e.g., String?) indicates that the variable can be nullable, meaning it can either hold a non-null value of that type or be null. On the other hand, if you declare a variable without ? (e.g., String), it means the variable must always contain a non-null value of that type.

    In your UserModel class, you have defined the fields as nullable:

    final String? username;
    final int? age;
    final String? phoneNumber;
    

    This means that these fields can be assigned null values. Whether you should use nullable or non-nullable types depends on the requirements of your application and how you want to handle null values. Here are some considerations:

    1. Use nullable types (String?, int?, etc.) when:

      • You expect that the data you receive may have missing values or nulls, and you want to represent that in your model.
      • You want to distinguish between a null value and an empty string, for example.
      • You want to avoid runtime null reference exceptions when accessing these fields.
    2. Use non-nullable types (String, int, etc.) when:

      • You expect that the data should always have a valid non-null value, and a null value would indicate a programming error or a data integrity issue.
      • You want to enforce that these fields are always initialized with valid values when creating an instance of the model.

    Regarding your second question about how to handle null values in the model or controller without cluttering the UI code, you can achieve this by providing default values or transforming the data when constructing the UserModel object. Here’s an example of how you can handle null values in the model constructor:

    class UserModel {
      final String username;
      final int age;
      final String phoneNumber;
    
      UserModel({
        String? username,
        int? age,
        String? phoneNumber,
      })  : username = username ?? 'Default Username',
            age = age ?? 0,
            phoneNumber = phoneNumber ?? 'N/A';
    
      @override
      String toString() {
        return 'Username => $usernamenAge => $agenPhone number => $phoneNumber';
      }
    }
    

    In this modified UserModel, if any of the provided values (username, age, or phoneNumber) are null, it will default to a specified value (e.g., ‘Default Username’ for username) instead of allowing null values. This way, you ensure that your UserModel always contains non-null values, which can make it easier to work with in the UI code.

    Login or Signup to reply.
  2. I will suggest to not include ? operator on class property. Now, it is not mandatory/forced to follow, but, from the perspective to reduce null exception, your code must be null safe, alternatively, you should use ? based on your need.

    In my experience, having a class like this, is a good-to-have structure.

    class UserModel {
      final String username;
      final int age;
      final String phoneNumber;
    
      UserModel({
        required this.username,
        required this.age,
        required this.phoneNumber,
      });
    }
    

    You can ask, what if my phoneNumber is not required to create a UserModel, how will I manage that. In that case, let’s **remove** the requried keyword from constructor of this.phoneNumber and assign a default value, the default value will only assign, if and only if, you didn’t provide any phoneNumber as argument, while creating an UserModel object.

    class UserModel {
      final String username;
      final int age;
      final String phoneNumber;
    
      UserModel({
        required this.username,
        required this.age,
        this.phoneNumber = "",
      });
    }
    

    another way to rewrite the same thing is

    class UserModel {
      final String username;
      final int age;
      final String phoneNumber;
    
      UserModel({
        required this.username,
        required this.age,
        required String? phoneNumber,
      }) : phoneNumber = phoneNumber ?? "";
    }
    

    For server data handling, I will recommend to use a factory constructor while maintaining the above structure.

    class UserModel {
      final String username;
      final int age;
      final String phoneNumber;
    
      UserModel({
        required this.username,
        required this.age,
        required this.phoneNumber,
      });
    
      factory UserModel.fromServer(Map<String, dynamic> map) {
        return UserModel(
          username: map["username"], // assuming username can't be null
          age: map["age"], // assuming age can't be null
          phoneNumber: map["phoneNumber"] ?? "",  // assuming phoneNumber can be null
        );
      }
    }
    

    To summarize the answer, you should avoid using nullable varialble most of the time. That doesn’t imply that you shouldn’t use nullable data type at all. What if you want to check if phoneNumber is provided or not by checking if the value is null or not. I mean who check the data is provided or not by checking if it is empty or not (acctualy I do).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search