Search code examples
flutterflutter-futurebuilder

From a `FutureBuilder`, my future never returns data


In a future builder, I use the following future that should return the number of documents (The collection stores "seen" event of an ad detailed view):


 /// Stores and returns the document [id].
  static Future<int> getCount({required String? adId}) {
    if (adId == null) return Future<int>.value(0);

    // = Actually store the document
    final c = FirebaseFirestore.instance
        .collection(collectionName)
        .where("adId", isEqualTo: adId)
        .snapshots()
        .length;

    return c;
  }

The FutureBuilder:

                    FutureBuilder(
                      future: ClassifiedAdSeen.getCount(adId: ad.id),
                      builder: (context, snapshot) {
                        if (snapshot.hasError) {
                          return const Icon(Icons.error);
                        } else if (!snapshot.hasData) {
                          return const CircularProgressIndicator();
                        }
                        final count = snapshot.data ?? "—";
                        return Text("$count");
                      }),

But it never hasData nor hasError, the spinner keeps on progressing.

Any idea Where the issue is, please?

[UPDATE]

By fetching the documents, I get the completion and the count with no problem. But fetching the documents is a waste of memory and bandwidth, isn't it?

So what would be the best way of fetching only the document count?


/// Stores and returns the document [id].
  static Future<int> getCount({required String? adId}) async {
    if (adId == null) return 0;

    // = Actually store the document
    final c = await FirebaseFirestore.instance
        .collection(collectionName)
        .where("adId", isEqualTo: adId)
        .get(); 

    return c.size;
  }

Solution

  • In your case, which is getting only the length of documents from your query, there is also a count() method that returns an AggregateQuery, which you don't get billed for, it returns only the length of the documents, nothing else.

    Give it a try:

    /// Stores and returns the document [id].
      static Future<int> getCount({required String? adId}) async {
        if (adId == null) return 0;
    
        // = Actually store the document
        final c = await FirebaseFirestore.instance
            .collection(collectionName)
            .where("adId", isEqualTo: adId)
            .count()
            .get(); 
    
        return c.count;
      }