Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to build a Stream based on a Future result in Flutter?

I have a Flutter app which uses Firebase-storage and google-signin. the steps I am trying to do is so simple:

1- Sign-in using Google (Done).

2- Get Current User Id (Done).

3- Use the User Id when construct the stream for the stream builder (the problem).

what I did so far is that I am using a Future to get the Current User Id, then to inject the user Id inside the Where clause

.where('userId', isEqualTo: userId)

and this is what I end up with:

this is the part where I should create the stream:

  // Get document's snapshots and return it as stream.
  Future<Stream> getDataStreamSnapshots() async {
    // Get current user.
    final User user = await FirebaseAuth().currentUser();
    String userId = user.uid;

    Stream<QuerySnapshot> snapshots =
      db
        .collection(db)
        .where("uid", isEqualTo: userId)
        .snapshots();

    try {
      return snapshots;
    } catch(e) {
      print(e);
      return null;
    }
  }

and this is the part where should I call and receive the stream,

...
children: <Widget>[
    StreamBuilder<QuerySnapshot>(
          stream: CALLING THE PREVIOUS FUNCTION,
            builder: (BuildContext context, 
                      AsyncSnapshot<QuerySnapshot> snapshot) {
                if (snapshot.hasData) {
                    ...
                }
              ...

But this code does not work, because I am not able to get the value that should returned by the Future? any idea?

thanks a lot

like image 462
Jehad Nasser Avatar asked Jun 25 '19 17:06

Jehad Nasser


People also ask

How do you use the Future in darts?

A future (lower case “f”) is an instance of the Future (capitalized “F”) class. A future represents the result of an asynchronous operation, and can have two states: uncompleted or completed. Note: Uncompleted is a Dart term referring to the state of a future before it has produced a value.

What is difference between Stream and Future?

The difference is that Futures are about one-shot request/response (I ask, there is a delay, I get a notification that my Future is ready to collect, and I'm done!) whereas Streams are a continuous series of responses to a single request (I ask, there is a delay, then I keep getting responses until the stream dries up ...


1 Answers

You should never have a Future<Stream>, that's double-asynchrony, which is unnecessary. Just return a Stream, and then you don't have to emit any events until you are ready to.

It's not clear what the try/catch is guarding because a return of a non-Future cannot throw. If you return a stream, just emit any error on the stream as well.

You can rewrite the code as:

Stream<QuerySnapshot> getDataStreamSnapshots() async* {
  // Get current user.
  final User user = await FirebaseAuth().currentUser();
  String userId = user.uid;

  yield* db
    .collection(db)
    .where("uid", isEqualTo: userId)
    .snapshots();
}

An async* function is asynchronous, so you can use await. It returns a Stream, and you emit events on the stream using yield event; or yield* streamOfEvents;.

like image 170
lrn Avatar answered Oct 19 '22 18:10

lrn