Flutter, Stream prints null even if there is data in firebase - flutter

I tried printing firebase data using stream, but instead of the data I got this in terminal " [ ] ". This means the data is null. But there is data in firebase, how do I solve this problem.
firebase's data
stream builder
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('paymentData')
.snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return const Center(
child: Text('Loading'),
);
}
print(snapshot.data!.docs);
return ListView(
children: snapshot.data!.docs.map((data) {
return ListTile(
title: Text(data['amount']),
);
}).toList());
},
),

Based on your firebase structure, there is no path called paymentData, it is actually a nested sub-collection, so in order to reach paymentData, you need to also include the parent of that collection, like this:
stream: FirebaseFirestore.instance
.collection('lender').doc(yourLenderId).collection('paymentData')
.snapshots(),
Get the lender ID from a previus step, which is the id of the document

Related

reading data from firebase firestore collection at stream builder

I got trouble with firebase fireStore.
There is a stream builder reading data from items collection.
Inside items collection there is some fields and another collections.
I haven't any problem with fields, the problem is with collection.
how to access those collections inside stream builder?
StreamBuilder<QuerySnapshot<Map<String, dynamic>>>(
stream: CallApi().finalReference(reference: widget.finalReference),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(child: Text('snapshot Error:${snapshot.error}'));
}
if (snapshot.hasData) {
var snapData = snapshot.data!.docs;
if (kDebugMode) {
print(snapData.length);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: ListView.builder(
itemCount: snapData.length,
itemBuilder: (BuildContext context, int index) {
return ListItem(
mTitle: snapData[index].get('title') ?? '',
mSubTitle: snapData[index].get('address') ?? 'empty',
mPrice: snapData[index].get('price') ?? '',
mImageUrl: snapData[index].get('gallery')[0],
mOnTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailsPage(
adsTitle: snapData[index].get('title'),
adsSubTitle: snapData[index].get('subTitle'),
gallery: snapData[index].get('gallery'),
specFTitle: snapData[index].get('gallery'),
),
),
);
},
);
},
),
),
],
);
}
return const Center(child: CircularProgressIndicator());
},
),
here is firebase
Reading data from Firestore is a shallow operation. When you read a document, its subcollection are not automatically read.
So if you want to get the data from the subcollections of the current document, you will have to start a new read operation for that. If you want to show that data in the UI, you can use a new, nested StreamBuilder or FutureBuilder for that.

Null check operator used on a null value FirebaseFirestore

I want to sort the posts in my application by date, but when I use orderby I get a null check operator used on a null value error. The problem is that when I type 'where' together with 'orderby' there is a problem.
My code below:
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('posts')
.where('uid', isEqualTo: widget.uid)
.orderBy(
'datePublished',
descending: true,
)
.snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
primary: false,
shrinkWrap: true,
itemCount: (snapshot.data! as dynamic).docs.length,
itemBuilder: (context, index) {
DocumentSnapshot snap =
(snapshot.data! as dynamic).docs[index];
Firestore is an optimized database. As a result, you have to create composite indexes for complex queries, like the one you are doing (combining orderBy with where), to work.
To solve this problem, look at the logs where you are running Flutter. you should see a Firebase Console link that will take you straight to creating the query. Create the query, wait for 5 minutes or less for it to build, then try the code again. It should work.
because stream can be return null value then snapshot.data! as dynamic make error. Please check snapshot.hasData
Add 1 more condition
if (snapshot.data == null) {
return const Center(
child: CircularProgressIndicator(),
);
}

(Flutter) StreamBuilder returns only null

I am trying to create a "CategoryStream" to update the UI based on the users choice.
This is my stream:
import 'dart:async';
class CategoryStream {
StreamController<String> _categoryStreamController =
StreamController<String>();
closeStream() {
_categoryStreamController.close();
}
updateCategory(String category) {
print("Update category in stream was called");
print("the new category is: " + category);
_categoryStreamController.sink.add(category);
}
Stream<String> get stream => _categoryStreamController.stream;
}
And my StreamBuilder looks like this:
return StreamBuilder<String>(
stream: CategoryStream().stream,
builder: (context, snapshot) {
return Container(
color: Colors.white,
child: Center(
child: Text(snapshot.data.toString()),
),
);
},
);
So when the User choses a new category, i try to update the Stream like this:
CategoryStream().updateCategory(currentChosenCategory);
Whatever i do, the result is always null. Although the right category is displayed in the print() function...
What am i missing?
Maybe i need to work with a StreamProvider? Not a StreamBuilder? Because i am adding the data from a Parent-Widget to a Child-Widget of a Child-Widget..
By default, the value of a StreamController is null. You need to set at initialData or add data to the stream before you call snapshot.data in your StreamBuilder:
final CategoryStream _categoryStream = CategoryStream();
return StreamBuilder<String>(
stream: _categoryStream.stream,
initialData: "",
builder: (context, snapshot) {
return Container(
color: Colors.white,
child: Center(
child: Text(snapshot.data), //toString() is unnecessary, your data is already a string
),
);
},
);

StreamBuilder shows only the results of the second MergeStream element

I'm trying to use a SearchDelegate() that can search among more than one stream. Now I'm trying to search among two. To merge both FireStore streams, I'm using MergeStream(). I'm not getting errors, but I only can see the results of the second stream. This is my code:
Stream stream1 =
FirebaseFirestore.instance.collection('stream1').snapshots();
Stream stream2 =
FirebaseFirestore.instance.collection('stream2').snapshots();
Stream<QuerySnapshot> mergedStream =
MergeStream([stream1, stream2]);
return StreamBuilder(
stream: mergedStream,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData)
return Center(
child: Text('Loading...'),
);
final results = snapshot.data.docs.where(
(DocumentSnapshot a) => a.data().toString().toLowerCase().contains(
query.toLowerCase(),
),
);
return Container(
margin: EdgeInsets.symmetric(vertical: 20.0),
child: ListView(................ etc,
Using Rx.combineLatest instead of merge

Firestore compound query not working for Flutter Web

Hi I have a simple query for Firestore in a StreamBuilder
StreamBuilder(
stream: FirestoreManager.firebaseFirestore
.collection("orders")
.orderBy('logs.0', descending: true)
.where('status', whereIn: current['id'])
.snapshots(),
builder: (BuildContext context, AsyncSnapshot<dynamic> snap) {
print(snap.data.toString());
if (!snap.hasError && snap.hasData) {
QuerySnapshot snapshot = snap.data;
if (snapshot.documents.isNotEmpty) {
List<DocumentSnapshot> snapList = snapshot.documents;
return ListView.builder(
padding: EdgeInsets.only(right: 10, left: 10),
physics: ScrollPhysics(),
itemCount: snapList.length,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return OrderListItem(
order: Order.fromJson(snapList[index].data),
);
},
);
} else {
return Center(
child: Text(
"No ${current['status'].toString().trim()} Order Available...!",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
);
}
} else {
return Center(
child: CircularProgressIndicator(),
);
}
})
It works absolutely fine for mobile appilcaiton but when I try to run it for web, It doesn't work.
Actually it shows data once for a second and again disappears. I got following log in console by printing snapshot data using print(snap.data.toString());
js_primitives.dart:30 null
js_primitives.dart:30 Instance of 'QuerySnapshot'
js_primitives.dart:30 null
Why is this happening? Why it shows data once and again disappear it?
If I remove either .orderBy('logs.0', descending: true) or .where('status', whereIn: current['id']) then it works fine.
I am having the same problem with flutter web. I am trying to use two chained where() methods and it doesn't give me any results:
StreamBuilder(
stream: fire
.collection('thiHistory')
.where("device", "==", _device)
.where("ts", '>=', ts)
.onSnapshot,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return Text('Loading....');
final docs = snapshot.data.docs;
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: docs.length,
itemBuilder: (context, index) {
final doc = docs[index].data();
return doc["device"] == _device ? Column(
children: [
Text(doc['device']),
Text("${doc["hour"]}"),
Text("${doc["temp"]}"),
Text("${doc["humi"]}"),
Text("${doc["thi"]}"),
],
) : Container();
});
},
)
If I only use one where() or the other it works fine. If I use both, I always get "Loading....", which tells me the snapshot has no data.
I also tried chaining orderedBy() with where() like Shahzad Akram, and same thing... Using one or the other works great, combining them does not return data.
I am using the firebase 7.3.0 package and version 7.19.1 of the libraries:
<script src="https://www.gstatic.com/firebasejs/7.19.1/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.19.1/firebase-database.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.19.1/firebase-firestore.js"></script>
Thanks for your help.