Flutter Firebase async query not retrieving data inside a stream function

Issue

I am trying to query a User from firebase within another query but for some reason but I can’t get the code to work

The function the wont run is await usersRef.doc(uid).get(); and can be found here:

static getUserData(String uid) async {
    return await usersRef.doc(uid).get();
  }

  static  DirectMessageListModel getDocData(QueryDocumentSnapshot qdoc, String uid)  {
    Userdata postUser = Userdata.fromDoc(getUserData(uid));
    return DirectMessageListModel.fromDoc(qdoc, postUser);
  }

  static DirectMessageListModel fromDoc(QueryDocumentSnapshot doc, Userdata altUser) {
    return DirectMessageListModel(
      doc['chatId'],
      doc['lastMsgContent'],
        doc['lastMsgType'],
        altUser
    );
  }

parent function:

Stream<List<DirectMessageListModel>> getMeassageList(){
    var snaps = FirebaseFirestore.instance.collection('directMessages').where('users', arrayContains: userdata!.uid).snapshots();
    List<String> usersListElement = [];

    return snaps.map((event) { return event.docs.map((e) {
      usersListElement = [e.get('users')[0], e.get('users')[1]];
      usersListElement.remove(userdata!.uid);
      return DirectMessageListModel.getDocData(e, usersListElement.first);
    }).toList();
    });


  }

Solution

You forgot to wait for the future getUserData(uid) to complete.

Try this:

static Future<DocumentSnapshot<Object>> getUserData(String uid) async {
  return await usersRef.doc(uid).get();
}

static DirectMessageListModel getDocData(
  QueryDocumentSnapshot qdoc,
  String uid,
) async {
  Userdata postUser = Userdata.fromDoc(await getUserData(uid)); // await here
  return DirectMessageListModel.fromDoc(qdoc, postUser);
}

..
// parent function.
// Also wait for the future in the parent function.

// UPDATE BELOW! Define the parent function like this:
Stream<List<Future<DirectMessageListModel>>> getMeassageList() {
  var snaps = FirebaseFirestore.instance
      .collection('directMessages')
      .where('users', arrayContains: userdata!.uid)
      .snapshots();
  List<String> usersListElement = [];

  return snaps.map((event) {
    return event.docs.map((e) async {
      usersListElement = [e.get('users')[0], e.get('users')[1]];
      usersListElement.remove(userdata!.uid);
      return await DirectMessageListModel.getDocData(e, usersListElement.first);
    }).toList();
  });
}

NB: You are fetching user data (either sender/receiver) for each message in directMessages collection. It might be better to store just sender/receiver name in directMessages collection and simply display that. Then if the user clicks on a message, you can then fetch the full sender/receiver data.

Answered By – Peter O.

Answer Checked By – David Goodson (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *