Does streambuilder from firebase rtdb will update list<User> user data?

Issue

currently I understadn with the method streamBuilder I can fetch updated data and add in the List<User> users.

But what if this user which is already added in the List<User> users has updated data, and then it could be double adding this user data in the List<User> users right?

  1. Could you plz show me how to confirm whether for the new coming data List<User> users has already same userId, if yes, the new data / userId will replace this exisiting userId?

  2. If the user is deleted from Firebase rtdb, the stream will be notified, and therefore remove this user from List<User> users?

here is example, my concern is since stream will always add data to the List users, but what if this user is removed from database or disconnect, how to remove this user from this list?

    _streamSubscription = availableUserStream.onValue.listen((snap) {
      if (snap.snapshot.exists && snap.snapshot.value != null) {
        DataSnapshot snapshotData = snap.snapshot;
    
        for (var userSnapshot in snapshotData.children) {
          final data = Map<String, dynamic>.from(userSnapshot.value as Map);
    
          List<User> users = [];
    
          User newUser = User.fromJson(data);
    
          users.add(newUser);
          firebaseController.setUsers(users: users);
    
        }
      }
    });

So I thought to do a double confirm here if this user is still exisitng in the database:

  User getRandomSenderUser({User asReceiverUser}) {
    if (availableSenderUsersList.isNotEmpty) {

      final random = Random();
      var i = random.nextInt(availableSenderUsersList.length);

      User randomUser = availableSenderUsersList[i];

      bool thisRandomUserIsAvailable; //TODO

I don’t know how to do this check, e.g. if this randomerUser is unavailable, so I need to get next randomUser, so it should be a loop? But it will slow down the response speed.

       updateSenderUserAvailableStatus(asReceiverUser:asReceiverUser,connectionUser: randomUser);
    
          return randomUser;
        } else {
          return null;
        }
      }



thank you!

Update:

Here is the example code, so now I understand stream will pass user data to List<User> users, but in my way there will always be user who is added in this list before, but was already removed from database, my plan is using while loop for double confirming to remove unavailable user when getting the randomUser, but it sounds not smart and still waste time I guess….

      @override
      void initState() {
        _listenAvailableUsers();
    }

    _listenAvailableUsers() {
        var availableUserStream =
            FirebaseDatabase.instance.ref().child('/waitingList');
    
        _streamSubscription = availableUserStream.onValue.listen((snap) {
          if (snap.snapshot.exists && snap.snapshot.value != null) {
            DataSnapshot snapshotData = snap.snapshot;
    
            for (var userSnapshot in snapshotData.children) {
              final data = Map<String, dynamic>.from(userSnapshot.value as Map);
    
              List<User> users = [];
    
              User newUser = User.fromJson(data);
    
              users.add(newUser);
              firebaseController.setUsers(users: users);
    
    
            }
          }
        });
      }

Here is the method I though to confirm if the randomUser is still existing in the database:

 Future<User> getRandomSenderUser({User asReceiverUser}) async {
    if (availableSenderUsersList.isNotEmpty) {

      User randomUser;

      while (true) {
        final random = Random();
        var i = random.nextInt(availableSenderUsersList.length);

        randomUser = availableSenderUsersList[i];

        DatabaseEvent event = await databaseReference
            .child('/waitingList/${randomUser.userId}')
            .once();
        print('randomUser is ${randomUser.toString()}');
        if (event.snapshot.value != null) {
          break;
        }
      }

      await updateSenderUserAvailableStatus(
          asReceiverUser: asReceiverUser, connectionUser: randomUser);

      print('connectionUserId is $connectionUserId');
      return randomUser;
    } else {
      return null;
    }
  }

Solution

Since you’re listening to the onValue of a path in the database, the DataSnapshot you get will contain the entire data at that path. When there was only a small change in the data, the server will only send that update to the client, but the SDK will then merge that with the existing data and still fire an event with a snapshot of all the data at the path.

Since you’re starting with an empty list (List<User> users = [];) each time you get an event from the stream, that means you’re rebuilding the entire lit of users each time, which seems correct to me.

Answered By – Frank van Puffelen

Answer Checked By – Marilyn (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published.