Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Do I convert Stream<QuerySnapshot> to List<myObject>

Tags:

flutter

dart

I'm querying Firestore and getting a Stream back as a Stream of QuerySnapshots. I need to map the included Documents in the stream to a List of objects.

The code below doesn't work (obviously)...maybe I'm just looking at this entirely wrong.

  List<UserTask> getUserTaskList() {
    List<UserTask> list;

    Stream<QuerySnapshot> stream = 
      Firestore.instance.collection('userTasks').snapshots();
    stream.listen((snapshot) {
      snapshot.documents.forEach((doc) {
        UserTask userTask = UserTask(
            doc.data['id'],
            doc.data['Description'],
            etc...);

        list.add(userTask);
      });
    });

    return list;
  }

With the code above, since it doesn't wait for the entire stream (or any of it actually), list is always returned as null. In short, how do I convert my stream to a List?

Note: I'm pretty new to the world of Dart, so go easy on me :)

Thanks!

like image 519
stevep Avatar asked Jul 22 '19 18:07

stevep


People also ask

What is QuerySnapshot in Swift?

A QuerySnapshot contains zero or more DocumentSnapshot objects. It can be enumerated using the documents property and its size can be inspected with isEmpty and count .

What is QuerySnapshot flutter?

A QuerySnapshot contains the results of a query. It can contain zero or more DocumentSnapshot objects. Subclassing Note: Cloud Firestore classes are not meant to be subclassed except for use in test mocks. Subclassing is not supported in production code and new SDK releases may break code that does so.

What is query snapshot?

A QuerySnapshot contains zero or more DocumentSnapshot objects representing the results of a query. The documents can be accessed as an array via the docs property or enumerated using the forEach method. The number of documents can be determined via the empty and size properties.


1 Answers

First of all, think about this: this function has to return very quickly. All functions do, otherwise UI would hang. However, you are expecting the function to return something that comes from the internet. It takes time. The function has to return. There is no way for a function to simply do a network request and return you the result. Welcome to the world of asynchronous programming.

Furthermore, the stream you have is not a stream of DocumentSnapshots (which you can convert to UserTasks), but a stream of QuerySnapshots (which you can convert to List<UserTask>s). Notice the plural there. If you simply want to get all your UserTasks once, you should have a Future instead of a Stream. If you want to repeatedly get all your UserTasks after each change, then using a Stream makes sense.

Since you said you want to get a List<UserTask>, I'm assuming you want to get the collection of UserTasks only once.

Here's what your code becomes in this light:

  Future<List<UserTask>> getUserTaskList() async {

    QuerySnapshot qShot = 
      await Firestore.instance.collection('userTasks').getDocuments();

    return qShot.documents.map(
      (doc) => UserTask(
            doc.data['id'],
            doc.data['Description'],
            etc...)
    ).toList();
  }

  main() async {
    List<UserTask> tasks = await getUserTaskList();
    useTasklist(tasks); // yay, the list is here
  }

Now if you really wanted to use a stream, here's how you could do it:

  Stream<List<UserTask>> getUserTaskLists() async {

    Stream<QuerySnapshot> stream = 
      Firestore.instance.collection('userTasks').snapshots();

    return stream.map(
      (qShot) => qShot.documents.map(
        (doc) => UserTask(
            doc.data['id'],
            doc.data['Description'],
            etc...)
      ).toList()
    );
  }

  main() async {
    await for (List<UserTask> tasks in getUserTaskLists()) {
      useTasklist(tasks); // yay, the NEXT list is here
    }
  }

Hope it helps.

like image 189
Gazihan Alankus Avatar answered Sep 17 '22 13:09

Gazihan Alankus