skip to Main Content

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.

2

Answers


  1. Chosen as BEST ANSWER

    After posting this question I thought of a way to resolve the problem that I had.

    I thought that if I could call the query from another class such as the class from which a recent navigation had occurred, then the data that StreamBuilder will not wait for a Future to deliver, could be made available in time for the Stream Builder. I tried this way and it worked perfectly.

    Another thing I found working on this solution, was that I didn't need the Firestore query at all, and this is because the data originated from the class that navigated towards the StreamBuilder's class. So, all I had to do was transfer some existing data.

    The technique I chose was to create a constructor for the class where the StreamBuilder was present, and then at the Navigator call, add the relevant data when calling that class. Doing this ensured that when the StreamBuilder began to build, the 'currency' value was available so that the StreamBuilder results could be filtered in accordance with the chosen currency.

    flutter: Login successful.
    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 = 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 = 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 = 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 = 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 = 230.0.
    flutter: The vehicle's pulling strength = 2300.0 bhp.
    flutter: The vehicle's brand is EEEEE, and its model-name is EEEEEEEEEE.
    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 = 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.

    The details above show the result of having the data required by the StreamBuilder transferred from another class.

    class StreamResults extends StatelessWidget {
    
      final _auth = auth.FirebaseAuth.instance;
      final _dB = FirebaseFirestore.instance;
      final _dataSource = FirebaseFirestore.instance
          .collection(
          'users/l9NzQFjN4iB0JlJaY3AI/userA/2VzSHur3RllcF5PojT61/exclusiveA');
    
      String? vehicleMake, vehicleTitle, currentUserID, pCurrency, currency, uid, docRefID;
      num? maxSpeed, pullStrength;
    
      StreamResults({this.uid, this.currency, this.docRefID});

    In the details above you can see the constructor for the StreamResults class which is a part of the solution.

    Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder:(context) => StreamResults(uid: uid, currency: currency, docRefID: docRefID)), (route) => false);

    The details above show the solution's Navigator call for changing screens and for transferring data at the same time.


  2. 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();
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search