StreamBuilder with Firestore loading vs no data - firebase

This feels a bit like a bug to me but I'm not sure. I have simple Firestore query in a Flutter app that I'm running through a Stream Builder. Looks something like this -
StreamBuilder(
stream: Firestore.instance.collection('users').where('toNumber', isEqualTo: '123').snapshots();
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
} else {
if (snapshot.data.length == 0) {
return Center(child: Text("No Data"));
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) =>
_buildList(
context, snapshot.data[index]),
);
}
}
)
The problem is that if the query returns no results then all you see in a continuous progress indicator. I would of thought hasData would return true but it seems this is not the case. I've also tried using ConnectionState but this always returns .waiting.
In this situation how would you differentiate between a query which is loading and a query which doesn't return any results?

Try the following :
if (!snapshot.hasData) {
if (snapshot.data.length == 0) {
return Center(child: Text("No Data"));
}
else{
return Center(
child: CircularProgressIndicator(),
);
}
}

Here is my build method. I've just tested it, it's working.
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: firestore
.collection('todos')
.where('state', isEqualTo: false)
.snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
print(snapshot.connectionState);
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return snapshot.data.documents.isNotEmpty
? ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (_, index) {
return Text(snapshot.data.documents[index].data["title"]);
})
: Text('No Data');
});
}
This prints:
I/flutter ( 6216): ConnectionState.waiting
I/flutter ( 6216): ConnectionState.active

Related

How to use get firebase data to StreamBuilder without Listview

I need to show my firebase data in deference places. But in the same page.
In every tutorial I followed they use Listview and I need to know there is another way to get data without using the list view
Ya finally I think I found an answer
final uid = FirebaseAuth.instance.currentUser!.uid;
userdata = FirebaseFirestore.instance.collection('/users/$uid/userdata');
return Scaffold(
body: StreamBuilder(
stream: userdata.snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
try {
snapshot.data!.docs.map((DocumentSnapshot document) {
data = document.data()! as Map<String, dynamic>;
}).toList();
} catch (e) {
print(e.toString());
}
},
),
);
Expanded(
child: StreamBuilder(
stream:
FirebaseFirestore.instance.collection("posts").snapshots(),
builder: (context,
AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>>
snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
log(snapshot.data!.docs[index].data().toString());
return UserVideos(
snap: snapshot.data!.docs[index].data(),
);
},
);
}
log("${snapshot.stackTrace}stack trace");
log("${snapshot.error}error");
return const Text("Something went wrong");
},
),
),

Firebase flutter _CastError (Null check operator used on a null value)

The documents on the tax page do not appear on the screen. I am getting the following _CastError (Null check operator used on a null value). Is there anyone who can help?
firestore_db_services.dart
#override
Stream<List<Vergi>> getHizmetler(String currentUserID) {
var snapShot = _firebaseFirestoreDB
.collection("hizmetler")
.doc(currentUserID)
.collection("vergi")
.orderBy("aciklamaDate")
.snapshots();
return snapShot.map(
(vergiListesi) => vergiListesi.docs
.map(
(vergi) => Vergi.fromMap(vergi.data()),
)
.toList(),
);
}
vergi.dart
Expanded(
child: StreamBuilder<List<Vergi>?>(
stream: _userModel.getHizmetler(_currentUser.userID),
builder: (context, snapShot) {
if (snapShot.hasError) {
return Center(
child: MyIndicator(),
);
}
if (snapShot.connectionState == ConnectionState.waiting) {
return Text("Yükleniyor...");
}
List<Vergi>? tumVergiListesi = snapShot.data;
return ListView.builder(
itemCount: tumVergiListesi!.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(
tumVergiListesi[index].aciklama.toString(),
),
subtitle: Text(
tumVergiListesi[index].fiyat.toString(),
),
);
},
);
},
),
),
Try returning snapshots from getHizmetler function and not the list you are currently returning:
Stream<QuerySnapshot>getHizmetler(String currentUserID) {
return _firebaseFirestoreDB
.collection("hizmetler")
.doc(currentUserID)
.collection("vergi")
.orderBy("aciklamaDate")
.snapshots();
}
Adjust your StreamBuilder like:
StreamBuilder<QuerySnapshot>(
stream: _userModel.getHizmetler(_currentUser.userID),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
// error handling
return ...;
}
if (snapshot.connectionState == ConnectionState.waiting) {
// progress indicator
return ...;
}
if (snapshot.hasData) {
// here you can do the conversion you like, result will be in:
// snapshot.data!.docs
}
}
)

The argument type 'User' can't be assigned to the parameter type 'Future<dynamic>'.? [duplicate]

This question already has answers here:
Undefined class 'FirebaseUser'
(6 answers)
Closed 1 year ago.
Im trying use Firebase instance like I normally did but in this case im getting an error and my question is How can I fix this error in my code:
The argument type 'User' can't be assigned to the parameter type 'Future<dynamic>'.
class Messages extends StatelessWidget {
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: FirebaseAuth.instance.currentUser,
builder: (context, futureSnapshot) {
if (futureSnapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator());
}
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection('chat')
.orderBy('created', descending: true)
.snapshots(),
builder: (context, chatSnapshot) {
if (chatSnapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
}
final chatdocs = chatSnapshot.data.docs;
return ListView.builder(
itemCount: chatdocs.length,
itemBuilder: (context, index) => MessageBubble(
chatdocs[index]['text'],
chatdocs[index]['userId'] == futureSnapshot.data.uid,
));
Hope anyone can help.
And maybe anyone can explain me this not just giving in answer
FirebaseAuth.instance.currentUser is of type User, it is not a Future.
Hence you do not need to use a FutureBuilder in this case.
class Messages extends StatelessWidget {
#override
Widget build(BuildContext context) {
final currentUser = FirebaseAuth.instance.currentUser;
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection('chat')
.orderBy('created', descending: true)
.snapshots(),
builder: (context, chatSnapshot) {
if (chatSnapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
}
final chatdocs = chatSnapshot.data.docs;
return ListView.builder(
itemCount: chatdocs.length,
itemBuilder: (context, index) {
return MessageBubble(
chatdocs[index]['text'],
chatdocs[index]['userId'] == currentUser.data.uid,
);
},
);
},
);
}
}

How to make list view to listview.builder in flutter?

buildComments() {
return StreamBuilder(
stream: commentRef
.document(postId)
.collection('comments')
.orderBy('timestamp', descending: false)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return circularProgress();
}
List<Comment> comments = [];
snapshot.data.documents.forEach((doc) {
print(comments);
comments.add(Comment.fromDocument(doc));
});
return ListView(
children: comments,
);
});
}
I was trying to convert it in list view.builder but it gives me error you can can't use list instead of Widget, Can anyone solve this problem.
You should do the following:
if (snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
contentPadding: EdgeInsets.all(8.0),
title: Text(snapshot.data.documents[index].data["name"]),
);
});
Assuming you have name in the document.

got an error in flutter require an identifier while using the streambuilder

I have created the widget in flutter app and its connected with the google firebase but i got an error on the StreamBuilder while getting the data document.('quick')
Widget _createBody() {
return StreamBuilder(
stream: Firestore.instance
.collection('notes').document.('quick').snapshots(),
builder: (context, snapshot){
if(snapshot.hasData){
var doc = snapshot.data;
if (doc.exists){
return Text(doc['content']);
}
}
return CircularProgressIndicator();
}
);
}
return StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('notes').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError)
return Center(
child: Text('Error: ${snapshot.error}'),
);
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Center(
child: Text('Loading...'),
);
default:
return new ListView(
children: snapshot.data.documents.map((
DocumentSnapshot document) {
return ListTile(
title: Text(document['content']),
);
}).toList(),
}
}
};
It should be something like this if you're fetching a single document.
Widget _createBody() {
return StreamBuilder(
stream: Firestore.instance
.collection('notes')
.document('quick')
.get()
.snapshots(),
builder: (context, snapshot){
if(snapshot.hasData){
var doc = snapshot.data;
if (doc.exists){
return Text(doc['content']);
}
}
return CircularProgressIndicator();
}
);
}
If this doesn't work, you can always change it like so:
Firestore.instance
.collection('notes')
.document('quick')
.get()
.then((DocumentSnapshot ds) {
// use ds as a snapshot
});

Resources