Flutter QuerySnapshot return null - firebase

What I really want to do is take all the ORDER IDs ("order_id") that are in the "deliver" collection and use these IDs in another call, that is, enter in "orders" collection and inform all IDs I got in the "deliver" collection as documents.
my stream:
function() {
Firestore.instance
.collection("delivers")
.document("fvRpb1xDOKejJ5AEqXEeThaqhci1")
.collection("orders")
.snapshots()
.listen((orders) {
orders.documents.forEach((f) {
print("+++++ First +++++ ${f.data}");
Firestore.instance
.collection("orders")
.document(f.documentID)
.snapshots();
});
});
}
My StreamBuilder Bellow:
body: Container(
child: StreamBuilder<QuerySnapshot>(
stream: function(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
print("SNAPSHOT DATA ++++++ ${snapshot.toString()} ++++++}");
// if (snapshot.hasError)
// print("ERRO EM ++++++ ${snapshot.error.toString()} ++++++}");
if (!snapshot.hasData)
return Center(
child: RaisedButton(
onPressed: function, child: Text("press")));
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return circularProgress();
break;
default:
print(
"CONNECTION DEFAULT ++++++ ${snapshot.toString()} ++++++}");
return ListView(
children: snapshot.data.documents
.map((DocumentSnapshot myOrder) {
return Text(myOrder["quantity"]);
}).toList());
}
}),
),
RETURNS:
I/flutter ( 600): +++++ First +++++ {order_id: 2tC5gbAYLoj375w9HrKc}
Performing hot reload... ⡿I/flutter ( 600): SNAPSHOT DATA ++++++ AsyncSnapshot(ConnectionState.none, null, null) ++++++}
my firestore screen shots
https://drive.google.com/drive/u/0/folders/1ZeXog80wvnR-6cTG2VCE0jOVfrSEyDaM

You are not returning anything from function().
Add return keyword before snapshots as :
return Firestore.instance
.collection("delivers")
.document("fvRpb1xDOKejJ5AEqXEeThaqhci1")
.collection("orders")
.snapshots();
or simply put the snapshot in front of the stream, as :
stream:Firestore.instance.collection('delivers').document('fvRpb1xDOKejJ5AEqXEeThaqhci1')____________.snapshots(),

I share a possible cause of problem of: "ALWAYS having null on snapshots results even the data is there in Firebase"
It might be your cloud_firestore version in pubspec.yaml caused the problem. I tried different methods of fetching data on Youtube, but none of them worked, I finally changed the version of cloud_firestore from ^0.14.4 to ^0.13.5, and the data suddenly all appeared! Here is my specific version changes in pubspec.yaml: the commented are the new version that does not work.
# cloud_firestore: ^0.14.4
cloud_firestore: ^0.13.5
firebase: ^7.3.3
# firebase_auth: ^0.18.4+1
firebase_auth: ^0.15.4
# firebase_core: ^0.5.3
firebase_core: ^0.4.4
This might not be the cause of your problem, but it may help some others :D

Related

my documents are not being uploaded to firebase

so i'm creating a todo list app, and it was working fine and all until i upgraded all the packages in my pubspec.yaml, which led to some nasty errors i found a way to fix it but that was when i started experiencing a problem, when i write tasks to my firestore database it doesn't add, and my stream builder doesn't see it but if i add the task manually, my stream builder still wont see it, i need help
how i solved my error in my pubspec
dependency_overrides:
firebase_messaging_platform_interface: 3.1.6
firebase_crashlytics_platform_interface: 3.1.13
cloud_firestore_platform_interface: 5.4.13
firebase_auth_platform_interface: 6.1.11
firebase_storage_platform_interface: 4.0.14
cloud_functions_platform_interface: 5.0.21
firebase_analytics_platform_interface: 3.0.5
firebase_remote_config_platform_interface: 1.0.5
firebase_dynamic_links_platform_interface: 0.2.0+5
firebase_performance_platform_interface: 0.1.0+5
firebase_app_installations_platform_interface: 0.1.0+6
how i add tasks to firebase
FirebaseFirestore.instance.collection('tasks').add(
{
'name': textcontrol,
'description': descriptionControl,
'completed': false,
'DOC': newDate,
'created': DateTime.now(),
'time': newTime.format(context).toString(),
},
);
my stream builder
StreamBuilder<QuerySnapshot>(
builder: (context, snapshot) {
if (!snapshot.hasData)
return Container(
height: constraints.maxHeight * 0.7,
child: Center(
child: Text('press the + icon to add a task'),
),
);
return Expanded(child: _buildList(snapshot.data));
},
stream: FirebaseFirestore.instance
.collection('tasks')
.where('completed', isEqualTo: false)
.snapshots(),
),
When you upload something on the firebase database you have to create a doc within the collection with a unique id and then set your Map, so your code must look like this:
FirebaseFirestore.instance.collection('tasks').doc(doc_name_you_want).set(
{
'name': textcontrol,
'description': descriptionControl,
'completed': false,
'DOC': newDate,
'created': DateTime.now(),
'time': newTime.format(context).toString(),
},
);

how to handle StreamBuilder listening to non-existent snapshot?

all i want to achieve is as long as the document exists in cloud firestore....my streambuilder keeps listening to its snapshots...if for some reason..the document has been removed from cloud firestore collection, i want to Navigator.of(context).pop() safely without any errors.
this is my StreamBuilder right now:
return StreamBuilder<DocumentSnapshot>(
stream: Firestore.instance
.collection('posts')
.document(widget.passedPostId)
.snapshots(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (!snapshot.hasData) {
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: CircularProgressIndicator(
valueColor:
AlwaysStoppedAnimation<Color>(Theme.of(context).primaryColor),
),
);
}
String postTitle = snapshot.data['postTitle'];
String postBody = snapshot.data['postBody'];
return Container(child: Column(children:[
Text('$postTitle'),
Text('$postBody'),
]));
}
);
from this point, everything works well as intended, but when i open the cloud firestore collection and manually delete the document from the collection...the App crashes and i get this error:
The method '[]' was called on null.
Receiver: null
Tried calling: []("postTitle")
so to recap:
i want to delete the document from cloud firestore collection manually...and the App safely determines that the document doesn't exist anymore...so it Navigator.of(context).pop() the current screen
Try utilising exists property on DocumentSnapshot.
https://pub.dev/documentation/firebase/latest/firebase_firestore/DocumentSnapshot/exists.html
if (!snapshot.hasData) {
return LoadingWidget();
}
if (!snapshot.data.exists) {
Future.delayed(Duration.zero).then((_) {
Navigator.of(context).pop();
});
return SizedBox();
}
return DataWidget();
The Future is a hack required to execute pop after building is complete. Alternatively you can use SchedulerBinding.addPostFrameCallback which will produce the same result.

Error showing when document is deleted from firestore with streambuilder (flutter)

Hello everybody first of all I'm sorry for my English if its not clear, I'm working on a personal project. so, I'm using StreamBuilder on firestore document with the userID of the user from 'Users' Collections. So, I have retrieved the "imageUrl" field and display it in Image Network in my application, so, I have 'Delete Account' Button, this button will delete the account from firebase auth and also delete the document that the streambuilder listens to it.
So, the error happens because the streambuilder will build ImageNetwork and retrieve the URL from the document field.
Any ideas to handle the error?
this is the code for the streamBuilder that will return NetworkImage
StreamBuilder<DocumentSnapshot>(
stream: Firestore.instance
.collection('Users')
.document(user.getID())
.snapshots(),
builder:
(context, AsyncSnapshot<DocumentSnapshot> snapshot) {
print(snapshot.connectionState);
var userDocument = snapshot.data;
if (userDocument.data.length == 0) {
return const Center(
child: Text(
"Not Available",
style:
TextStyle(fontSize: 30.0, color: Colors.grey),
),
);
} else
return AvatarGlow(
glowColor: Colors.redAccent,
endRadius: 90,
child: Material(
elevation: 8.0,
shape: CircleBorder(),
child: CircleAvatar(
backgroundColor: Colors.grey[100],
child: ClipOval(
child: FadeInImage(
image: NetworkImage(
userDocument['imageUrl'] ??
'https://picsum.photos/250?image=9'),
placeholder: AssetImage('assets/noImage.png'),
),
),
radius: 70,
),
),
);
},
),
Debug error
The getter 'length' was called on null.
Receiver: null
Tried calling: length
The relevant error-causing widget was
StreamBuilder<DocumentSnapshot>
The solution was on if else blocks
StreamBuilder<DocumentSnapshot>(
stream: Firestore.instance
.collection('Users')
.document(user.getID())
.snapshots(),
builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.data != null && snapshot.data.exists) {
var userDocument = snapshot.data;
// return something
}
}
For a non-existing document userDocument.data will return null, so userDocument.data.length throws the error you get.
My guess is you want to check if the document exists, which you'd do with:
if (userDocument.exists) {
Also see the reference documentation on DocumentSnapshot class, which is the type of object your userDocument is.
Ok. So, how these StreamBuilder(s) and FutureBuilder(s) are supposed be used are as follows:
Note: the following code should be inside your Builder function.
if(snapshot.hasData){
// Your normal functioning of the app will follow here.
// Now that you know that your snapshot contains data,
// then you access the data.
var userDocument = snapshot.data;
// Now, you can check if the userDocument exists or not.
}
else if(snapshot.hasError){
// return an error message or do something else.
}
// return any default Widget while the data is being loaded.
return CircularProgressIndicator();
Also, I would recommend that once the user requests to delete his/her account, you should navigate back to the home screen...

How to arrange cloud firestore documents in serial wise with flutter?

I'm trying to create chat demo app with firebase in flutter but when i send message, then those message documents are being created at randomly any places in firestore database. thats why my chat screen messages are in wrong manner, means not arranged according to time.
Some piece of code:
method for saving message details to firestore:
Future<void> sendMesssage() async{
if(messagesController.text.length>0){
String msgId = firestore.collection("messages").document().documentID.toString();
await firestore.collection("messages").document(msgId).setData({
'text': messagesController.text,
"from": widget.user.user.email, //sender email Id
"to":widget.chatMateEmail, // receiver email id
"msgId":msgId,
"senderUid": widget.user.user.uid, //sender uid
"receiverUid":widget.receiverUid //receiver uid
});
messagesController.clear();
}
}
UI For chat screen:
method for fetching messages from firestore:
Expanded(
child: StreamBuilder<QuerySnapshot>(
stream: firestore.collection("messages").snapshots(),
builder: (context, snapshot){
if(snapshot.hasError){
return Center(child: Text("${snapshot.error}"),);
}
if(!snapshot.hasData){
return Center(child: CircularProgressIndicator(),);
}else{
List<DocumentSnapshot> docs = snapshot.data.documents;
return
Padding(
padding: const EdgeInsets.all(8.0),
child: ListView.builder(
itemCount: docs.length,
itemBuilder: (context, index){
print("Messagessssssss:${docs[index]['text']}");
return Message( // custom class
from: docs[index]['from'],
text: docs[index]['text'],
me: widget.user.user.email == docs[index]['from'],
);
},
),
);
}
},
),
),
chat Screen:
My Cloud Firestore Screenshot:
It got solved according to #DougStevenson sir's answer, I added new field with name "messageTime" and add DateTime.now(), And fetched messages according to messageTime (sort by ascending order ).
I modified a little bit my code & working perfectly:
Future<void> sendMesssage() async{
if(messagesController.text.length>0){
String msgId = firestore.collection("messages").document().documentID.toString();
await firestore.collection("messages").document(msgId).setData({
..........
"messageTime": DateTime.now() // message DateTime
});
messagesController.clear();
}
}
Expanded(
child: StreamBuilder<QuerySnapshot>(
stream: firestore.collection("messages").orderBy('messageTime', descending: false).snapshots(), //and sort by ascending order according to datetime.
builder: (context, snapshot){
......
},
),
),

A simple where clause in flutter/firebase database

Today I started experimenting with Firebase Live database. Maybe I'm thinking too much in sql terms. But what I want to do is get a record from my database where a value equals a variable with flutter. My table looks like this:
What I'm trying to achieve is something like this:
FirebaseDatabase.instance.reference().child('users').where('User_id', 1508)
Like I said. I'm a complete beginner when it comes to Live Databases.
I hope someone can help me with this issue I'm having.
Kind regards,
Namanix
According to firstore docs
Firestore.instance
.collection('talks')
.where("topic", isEqualTo: "flutter")
.snapshots()
.listen((data) =>
data.documents.forEach((doc) => print(doc["title"])));
If you have the user id in a variable for example called:
String uid = currentUser.uid;
then you can do the following:
FirebaseDatabase.instance.reference().child('users/$uid')
Update
I think this is what you are asking about
FirebaseDatabase.instance
.reference().child("users")
.orderByChild("User_id")
.equalTo($this.userId)
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder<QuerySnapshot>(
future: FirebaseFirestore
.instance
.collection('users')
.where("user_id", isEqualTo: FirebaseAuth.instance.currentUser!.uid)// 👈 Your where condition here
.get(),
builder: (_, snapshot) {
if (snapshot.hasError) return Text('Error = ${snapshot.error}');
if (snapshot.connectionState == ConnectionState.waiting) {
return const Text("Loading");
}
return ListView(
children: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
return ListTile(
title: Text(data['avatar']), // 👈 Your valid data here
);
}).toList());
},
)),
);
}
Also refer: How to use StreamBuilder and FutureBuilder for single and multiple documents

Resources