Search code examples
flutterfirebasegoogle-cloud-firestorestream-builder

How can I get StreamBuilder results after a Firestore query has been completed?


I have a query for retrieving data from a Firestore collection, and values from that query are used to define the stream to be built by StreamBuilder.

What I have found is that StreamBuilder builds the stream before the Firestore query has been completed, which produces a different result than if the query had completed and then StreamBuilder had built.

@override
  Widget build(BuildContext context) {
    getData();
    final _dataSource = FirebaseFirestore.instance
        .collection(
        'users/l9NzQFjN4iB0JlJaY3AI/userA/2VzSHur3RllcF5PojT61/exclusiveA');
    return StreamBuilder<QuerySnapshot>(
        stream: _dataSource.where('preferredCurrency', isEqualTo: currency).snapshots().distinct(), // exclusiveA is being read
        // results should return only documents where preferredCurrency field = the value of currency field
        builder: (context, snapshot) {

Is there a way for Flutter to be written so that a Future type of query can be completed before the UI is built with StreamBuilder?

flutter: Login successful.
flutter: The vehicle's maximum speed = 233.0.
flutter: The vehicle's pulling strength = 2222.0 bhp.
flutter: The vehicle's brand is CCCCC, and its model-name is BBBBB.
flutter: The preferred currency = GBP.
flutter: The vehicle's maximum speed = 220.0.
flutter: The vehicle's pulling strength = 9000.0 bhp.
flutter: The vehicle's brand is PPPPP, and its model-name is LLLLL.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 235.0.
flutter: The vehicle's pulling strength = 440.0 bhp.
flutter: The vehicle's brand is KEXUZ, and its model-name is N2000.
flutter: The preferred currency = YEN.
flutter: The vehicle's maximum speed = 88.0.
flutter: The vehicle's pulling strength = 1100.0 bhp.
flutter: The vehicle's brand is Eord, and its model-name is Eiesta.
flutter: The preferred currency = GBP.
flutter: The vehicle's maximum speed = 110.0.
flutter: The vehicle's pulling strength = 2000.0 bhp.
flutter: The vehicle's brand is Zadilax, and its model-name is Zrechlax.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = 300.0.
flutter: The vehicle's pulling strength = 3200.0 bhp.
flutter: The vehicle's brand is XXXXX, and its model-name is XXXXXXXXXX.
flutter: The preferred currency = YEN.
flutter: The vehicle's maximum speed = 2000.0.
flutter: The vehicle's pulling strength = 2000.0 bhp.
flutter: The vehicle's brand is MMMMM, and its model-name is MATHEMS.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = 110.0.
flutter: The vehicle's pulling strength = 2000.0 bhp.
flutter: The vehicle's brand is Zadilax, and its model-name is Azerlax.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = 2000.0.
flutter: The vehicle's pulling strength = 2000.0 bhp.
flutter: The vehicle's brand is AAAAAAAAA, and its model-name is BBBBBBBBB.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = 280.0.
flutter: The vehicle's pulling strength = 2234.0 bhp.
flutter: The vehicle's brand is ABCDE12345, and its model-name is TEST MAY 24.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = null.
flutter: The vehicle's pulling strength = null bhp.
flutter: The vehicle's brand is , and its model-name is .
flutter: The preferred currency = .
flutter: The vehicle's maximum speed = 120.0.
flutter: The vehicle's pulling strength = 320.0 bhp.
flutter: The vehicle's brand is Snow Patrol, and its model-name is HD Rider 100.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = 2000.0.
flutter: The vehicle's pulling strength = 2000.0 bhp.
flutter: The vehicle's brand is AAAAAAAA, and its model-name is BBBBBBBB.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 220.0.
flutter: The vehicle's pulling strength = 3200.0 bhp.
flutter: The vehicle's brand is Neverlet, and its model-name is NL 5000.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = 1234.0.
flutter: The vehicle's pulling strength = 1111.0 bhp.
flutter: The vehicle's brand is XXXXXZZZZZ, and its model-name is SASSCF.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = 123456789.0.
flutter: The vehicle's pulling strength = 123456.0 bhp.
flutter: The vehicle's brand is MAY 22, and its model-name is Y2023.
flutter: The preferred currency = YEN.
flutter: The vehicle's maximum speed = 2000.0.
flutter: The vehicle's pulling strength = 2000.0 bhp.
flutter: The vehicle's brand is XXXXX, and its model-name is ZZZZZ.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 250.
flutter: The vehicle's pulling strength = 500 bhp.
flutter: The vehicle's brand is CMW, and its model-name is K325S.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = 80.0.
flutter: The vehicle's pulling strength = 1200.0 bhp.
flutter: The vehicle's brand is Niatt, and its model-name is POQ 123.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 225.0.
flutter: The vehicle's pulling strength = 12345.0 bhp.
flutter: The vehicle's brand is TTTTT, and its model-name is YYYYY.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = null.
flutter: The vehicle's pulling strength = null bhp.
flutter: The vehicle's brand is Percedes B, and its model-name is XLK.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 100.0.
flutter: The vehicle's pulling strength = 1000.0 bhp.
flutter: The vehicle's brand is WWWWW, and its model-name is WATCHEMS.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 200.
flutter: The vehicle's pulling strength = 500 bhp.
flutter: The vehicle's brand is Vercedes, and its model-name is QWE223.
flutter: The preferred currency = GBP.
flutter: The vehicle's maximum speed = 235.0.
flutter: The vehicle's pulling strength = 900.0 bhp.
flutter: The vehicle's brand is Percedes ZZ, and its model-name is ASLK.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 2222.0.
flutter: The vehicle's pulling strength = 1234.0 bhp.
flutter: The vehicle's brand is Vvvvvvvv, and its model-name is Aaaaaaaaa.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 500.0.
flutter: The vehicle's pulling strength = 500.5 bhp.
flutter: The vehicle's brand is J5 Ingram, and its model-name is B Way.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = 235.0.
flutter: The vehicle's pulling strength = 550.0 bhp.
flutter: The vehicle's brand is Vercedes ZXC, and its model-name is X46i.
flutter: The preferred currency = Euros.
flutter: The vehicle's maximum speed = 876543.0.
flutter: The vehicle's pulling strength = 1234.0 bhp.
flutter: The vehicle's brand is Ssssssss, and its model-name is Zzzzzzz.
flutter: The preferred currency = ZZZ.
flutter: The vehicle's maximum speed = 250.5.
flutter: The vehicle's pulling strength = 770.7 bhp.
flutter: The vehicle's brand is Vercedes ZXC, and its model-name is L55i.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 2800.0.
flutter: The vehicle's pulling strength = 1100.0 bhp.
flutter: The vehicle's brand is ZZZZZ, and its model-name is ZAPPEMS.
flutter: The preferred currency = EUR.
flutter: The current user's ID is: gaWoPCiLPWef9mCmd6WngDiS1I63 and their currency-choice = YEN.

The details above show the result where the Future type query isn't completed before the StreamBuilder begins to build: a print statement to Flutter's console from the Future query is the very last output from Flutter, whereas the stream is the entire collection's data.

What's meant to happen is, the Future query should complete first and confirm the 'currency' value, then the StreamBuilder results should be filtered to show only the results where the currency matches the 'currency' value from the query.


Solution

  • Yes, in flutter you can wait till Future task compete its execution with FutureBuilder widget.

    Here is your updated code

    @override
    Widget build(BuildContext context) {
      return FutureBuilder<QuerySnapshot>(
        future: getFutureData(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            // Show a loading indicator while the query is being executed
            return CircularProgressIndicator();
          }
    
          if (snapshot.hasError) {
            // Handle any error that occurred during the query
            return Text('Error: ${snapshot.error}');
          }
    
          final _dataSource = snapshot.data.docs; // Access the documents from the query result
    
          return StreamBuilder<QuerySnapshot>(
            stream: _dataSource
                .where('preferredCurrency', isEqualTo: currency)
                .snapshots()
                .distinct(),
            builder: (context, snapshot) {
              // Build your UI based on the snapshot of the stream
              // ...
            },
          );
        },
      );
    }
    
    Future<QuerySnapshot> getFutureData() {
      final collectionRef = FirebaseFirestore.instance.collection(
          'users/l9NzQFjN4iB0JlJaY3AI/userA/2VzSHur3RllcF5PojT61/exclusiveA');
      return collectionRef.get();
    }