How to save correctly data into my model from an StreamBuilder

Viewed 323

So I was wondering what'd the best way to save data into my model. I noticed there's not too much infotmation when it comes about StreamBuilder and Models. (both together I mean).

This is my current model.

class User {
  String _username, _name, _dateBorn, _gender;

  bool _isObserver, _notifyFriends, _recordAudio, _sendTweet;

  List<dynamic> _friendList;
  List<dynamic> _pendingFriends;

  User(
      this._username,
      this._name,
      this._dateBorn,
      this._gender,
      this._isObserver,
      this._notifyFriends,
      this._recordAudio,
      this._sendTweet,
      this._friendList,
      this._pendingFriends);

  String get username => _username;
  String get name => _name;
  String get dateBorn => _dateBorn;
  String get gender => _gender;

  bool get isObserver => _isObserver;
  bool get notifyFriends => _notifyFriends;
  bool get recordAudio => _recordAudio;
  bool get sendTweet => _sendTweet;

  set setNotifyFriends(bool value) => _notifyFriends = value;
  set setRecordAudio(bool value) => _recordAudio = value;
  set setSendTweet(bool value) => _sendTweet = value;

  List<dynamic> get friendList => _friendList;
  List<dynamic> get pendinFriends => _pendingFriends;
}

and this is my current FireStore Database.

enter image description here

Right now what I'm doing is this.

StreamBuilder(
            stream:
                FirebaseFirestore.instance.collection('Usuarios').snapshots(),
            builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
              if (!snapshot.hasData) {
                return Center(
                  child: CircularProgressIndicator(),
                );
              }

              var data = snapshot.data!.docs;
              var user;

              data.forEach((element) {
                if (element["username"] == me) {
                  user = User(
                    element["username"],
                    element["realName"],
                    element["date_birth"],
                    element["sexo"],
                    element["isObserver"],
                    element["config"]["notifyFriends"],
                    element["config"]["recordAudio"],
                    element["config"]["sendTweet"],
                    element["friends"],
                    element["pendingFriends"],
                  );
                }
              });

              return FriendsWidget(user);
            }),

But I'm pretty sure this isn't a good practice, what'd be the best practice to give the data to the model? Without losing the update-data-in-real-time feature?

Thanks!

1 Answers

We can make use of json_serializable package available in Flutter to ease the JSON parsing and assign it to respective model class instead of assigning it manually.

You can create a methods fromJson and toJson to parse JSONObjects. However , we may need to setup some dev dependencies to make that work in our project. Please refer the documentation at Flutter

Usage will be simple like below

FirebaseFirestore.instance.collection('allUsers').snapshots().listen((event) {
    for (var element in event.docChanges) {
        final modelData = UserModel.fromJson(element.doc.data());
        // Do anything with your user. For example adding to list. 
    }
});

Model class

part 'user_model.g.dart';

@JsonSerializable()
class UserModel {
  @JsonKey(name: 'user_id')
  String userId;

  @JsonKey(name: 'name')
  String name;
  
  UserModel();

  factory UserModel.fromJson(Map<String, dynamic> json) => _$UserModelFromJson(json);

  Map<String, dynamic> toJson() => _$UserModelToJson(this);
}

Usage of json_serializable with firestore are explained in the below articles. Have it as a reference.

firestore-with-flutter-json-annotation

flutter-using-json_serializable-to-serialise

https://livebook.manning.com/book/flutter-in-action/chapter-10/v-7/54

Details are provided in bits and pieces in the example links. You may need to work it out to fit best for your requirement.

Related