BLoC copyWith method and ChatState

Created At: 2023-07-05 19:02:22 Updated At: 2023-07-06 08:15:10

Chatting could be a difficult topic for most beginners and they don't know how maintain state of the page. Here we will see how we can use BLoC library to manage the state of the chatting list along with copyWith() and update the state of the message or chat object.

In this example we will assume the data would be coming from external resources like server or Firebase. Each of the message coming from server would contain a text, token, timestamp and other related information. We will incapsulate those information into an object.

We will create a model class for it. We will call it Msgcontent. Every message we get will follow the class pattern and use these information to make an object using Msgcontent. The class itself looks like below

class Msgcontent {
  final String? token;
  final String? content;
  final String? type;
  final Timestamp? addtime;

  Msgcontent({
    this.token,
    this.content,
    this.type,
    this.addtime,
  });
}

Apart from these, we will also get other information from server like token of the user who sent it, person's avatar, name and other information of the sender. Those information you may see from the class below.

Our class below we call it ChatState and it contains Msgcontent and other related information about the sender in it's constructor.

  final String to_token;
  final String to_name;
  final String to_avatar;
  final String to_online;
  final bool isloading;
  final bool more_status;
  final List<Msgcontent> msgcontentList;

These are fields that constructor initializes. These are also the fields that we use for creating a new object. In general you use all the fields to create a new object. But in this case we won't do like this. We will use part of the fields to create a new object. This will happen through a method called copyWith().

This class also contains a copyWith() method. It's a fancy name and but you can name it any thing. But what it does is most important.

It helps to create a new object with given information. The information could be all the fields in the constructor or part of the information.

copyWith() method

  ChatState copyWith({
    String? to_token,
    String? to_name,
    String? to_avatar,
    String? to_online,
    bool? isloading,
    bool? more_status,
    List<Msgcontent>? msgcontentList,
  }) {
    return ChatState(
      to_token: to_token ?? this.to_token,
      to_name: to_name ?? this.to_name,
      to_avatar: to_avatar ?? this.to_avatar,
      to_online: to_online ?? this.to_online,

      isloading: isloading ?? this.isloading,
      more_status: more_status ?? this.more_status,
      msgcontentList: msgcontentList ?? this.msgcontentList,
    );
  }

The method returns a ChatState object as you can see from the return statement. And all the parameters in the method is optional, that means you may provide all or some or not at all, as arguments when you call the method.

Even with the part of the fields, copyWith method will return a new object. If some fields are missing in the parameters, then copyWith() will take the information from their earlier values from the object. This means all the fields of the constructor will have default values.

If you see the constructor, you will all the values are initialized with default values. So if copyWith method does not find values in the parameters, it takes the values from the constructor default values or the very earlier value of the the certain field.

Let's see how to create copyWith method for working with ChatState class. 

class ChatState extends Equatable {
  const ChatState({
    this.to_token="",
    this.to_name="",
    this.to_avatar="",
    this.to_online="",
    this.isloading = false,
    this.more_status = false,
    this.msgcontentList = const <Msgcontent>[],
  });

  final String to_token;
  final String to_name;
  final String to_avatar;
  final String to_online;
  final bool isloading;
  final bool more_status;
  final List<Msgcontent> msgcontentList;


  ChatState copyWith({
    String? to_token,
    String? to_name,
    String? to_avatar,
    String? to_online,
    bool? isloading,
    bool? more_status,
    List<Msgcontent>? msgcontentList,
  }) {
    return ChatState(
      to_token: to_token ?? this.to_token,
      to_name: to_name ?? this.to_name,
      to_avatar: to_avatar ?? this.to_avatar,
      to_online: to_online ?? this.to_online,

      isloading: isloading ?? this.isloading,
      more_status: more_status ?? this.more_status,
      msgcontentList: msgcontentList ?? this.msgcontentList,
    );
  }


  @override
  List<Object> get props => [to_token,to_name,to_avatar,to_online,msgcontentList,isloading,more_status];
}

copyWith() method creates immutable object. Which means you can not destroy or edit the object you create. One of the way to understand why it's immutable, you can understand from the constructor modifer const. If you put const modifier, it becomes immutable which means you won't be able to edit it.

Another thing why copyWith() method returns immtuable object is that you see, all of our fields are final. If all the fields are final and constructor has const modifier, the return object must be immutable.

Immutable objects are safe and easy to pass around. If you pass around immutable object, you don't need to worry that, they will be editted. 

Because nobody can edit them. So this is very safe for saving or recoding or storing data. That's how our chat state also becomes safe.

Comment

Add Reviews