SLendeR
SLendeR

Reputation: 947

StreamBuilder's Firebase query appears and disappears instantly

I am trying to query a Stream where the document should have 'UretimKurulum' in 'unit' array and the 'date' should be equal or greater than today's date.

While streaming this query I do get the correct results that I want for a brief seconds and then it says 'No Data Available'.

Database

Below is the actual code:

  final FirebaseFirestore _db = FirebaseFirestore.instance;

  final DateTime _now = DateTime.now();
  final String val = 'UretimKurulum';

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<QuerySnapshot<Object>>(
      stream: _db.collection('Schedule').where('date', isGreaterThanOrEqualTo: _now).where('unit', arrayContains: val).snapshots(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Center(child: LinearProgressIndicator());
        } else {
          if (!snapshot.hasData) {
            return Center(child: Text('No Data Available'));
          } else {
            return ListView.builder(
              itemCount: snapshot.data!.docs.length,
              itemBuilder: (context, index) {
                var docSnap = snapshot.data!.docs[index];
                return Text(docSnap.id);
              },
            );
          }
        }
      },
    );
  }
}

If I try to remove:

if (!snapshot.hasData) {
            return Center(child: Text('No Data Available'));
          }

I get the following error:

════════ Exception caught by widgets library ═══════════════════════════════════
The following TypeErrorImpl was thrown building StreamBuilder<QuerySnapshot<Object>>(dirty, state: _StreamBuilderBaseState<QuerySnapshot<Object>, AsyncSnapshot<QuerySnapshot<Object>>>#0508a):
Unexpected null value.

Error Message

Upvotes: 2

Views: 721

Answers (4)

Yogi Arif Widodo
Yogi Arif Widodo

Reputation: 679

  1. why you try remove the checkdata ?, the UX in general standard should display no data if the data is null or empty. for avoid null, you can use elvis operator like data ?? 'default-data' or data == null ? 'no-data' : 'found-data'
  2. good for datetime condition is using DateTime.now().microsecondsSinceEpoch instead of DateTime.now() this optional but more precise data is effectively https://docs.w3cub.com/dart~2/dart-core/datetime/microsecondssinceepoch
  3. you can try change
// instead of
       if (!snapshot.hasData) {
            return Center(child: Text('No Data Available'));
          } else {
            return ListView.builder(
              itemCount: snapshot.data!.docs.length,
              itemBuilder: (context, index) {
                var docSnap = snapshot.data!.docs[index];
                return Text(docSnap.id);
              },
            );
          }
// try this
       if (!snapshot.hasData) {
            return Center(child: Text('No Data Available'));
       } 
       return ListView.builder(
           itemCount: snapshot.data!.docs.length,
           itemBuilder: (context, index) {
              var docSnap = snapshot.data!.docs[index];
              return Text(docSnap.id);
           },
        );
          

Upvotes: 0

SLendeR
SLendeR

Reputation: 947

And indeed it was an indexing issue as @blaneyneil and myself stated previously.

The solution was to create a composite collection index from the Firebase Console and index the fields 'todoUnit' as Arrays and 'date' as Ascending.

enter image description here

Upvotes: 0

Yashir khan
Yashir khan

Reputation: 486

First thing first

 //instead of DateTime 
 final DateTime _now = DateTime.now();
 //you should use Timestamp which is provided by Firebase Firestore
 final Timestamp timeNow = Timestamp.now();

and second thing

//instead of
where('unit', arrayContains: val)
//try this
where("unit", "arrayContains", val)

Hope it should work if doesn't then reply me I will try to find other solution.

Upvotes: 2

blaneyneil
blaneyneil

Reputation: 3222

you'll get that blink when you haven't created the necessary indexes in Firestore. you need to create indexes for any queries that involve >, >=, <, <=. in your case, you should have something like the below in your firestore.indexes.json:

{
  "collectionGroup": "Schedule",
  "queryScope": "COLLECTION",
  "fields": [
    {
      "fieldPath": "unit",
      "arrayConfig": "CONTAINS"
    },
    {
      "fieldPath": "date",
      "order": "ASCENDING"
    }
  ]
},

or, if you prefer, just do it manually from your Firestore console.

Upvotes: 1

Related Questions