Issue in firestore database - flutter

I want to show current user data in my flutter app. But it print on screen " No data found".
This my database data
That error also happened error
My security rule
enter image description here
Here is my code
Container(
child: StreamBuilder(
stream: FirebaseFirestore.instance.collection("user3").where("id",isEqualTo:FirebaseAuth.instance.currentUser!.uid).snapshots(),
builder: (BuildContext context,AsyncSnapshot<QuerySnapshot> snapshot){
if(!snapshot.hasData){
return Text("Loading please wait........");
}
if (snapshot.hasData && snapshot.data!.docs.length > 0) {
DocumentSnapshot userData = snapshot.data!.docs[0];
// Build the widget using the userData
} else {
return Center(child: Text("No data found"));
}
return Container();
},
),
),

The long numeric values (e.g. "167582...") in your database screenshot do not look like a UID that any of the Firebase Authentication providers would generate.
Add this code right before you query the database:
print(FirebaseAuth.instance.currentUser!.uid)
This will show you the value that you're querying for, which (given my opening statement) probably looks quite different from the value in your database.
If that is indeed the case, the problem starts when you write the document. At that point you'll want to make sure that you write the value of FirebaseAuth.instance.currentUser!.uid to the id field.

Related

Does Streambuilder store the data after app restarts?

I have a simple streambuilder that reads the users document, and I use it to show some of the user's data. My question is, would this streambuilder re-read the document everytime the user restarts the app? If, yes is there any way to prevent the streambuilder from re-reading it everytime the user restarts the app unless there is a change in the document?
StreamBuilder(
stream: _firestore
.collection('users')
.doc(_auth.currentUser!.uid)
.snapshots(),
builder:
(context, AsyncSnapshot<DocumentSnapshot<Object?>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator(
color: isDarkMode ? Colors.white : Colors.black,
);
}
if (snapshot.hasData) {
if (snapshot.data!.exists) {
snapshot.data!['serviceEnabled'] == true
? startServices()
: null;
return Center(
child: Column(
This streambuilder is on the homepage of the app, I show some of the user's data on the homepage.
How would the database know whether there's a change in the document without reading that document?
If you can answer that, you can probably write a query to match that same condition.
For example, if each document has a lastUpdated field, you could just get the updated document with:
_firestore
.collection('users')
.where('lastUpdated', '>', timestampWhenYouLastReadDocuments)
.get()
Aside from that query to update the cache, you could then get the documents from the cache in other places in your app.

Flutter: CircularProgressIndicator not showing even though Stream returns no values

I have a StreamBuilder in order to get data from my user collection in Firestore to get their profile image. This works fine. But when for example I turn off my internet, then instead of showing a CircularProgressIndicator, it just shows my CircularAvatar with the backgroundColor.
Please see my code below. Normally when I turn off the internet, the code below should return the Progress Indicator. Why is that not happening? And when I then turn the internet back on, it does not update and show the correct profile image. Is the stream not working correctly?
StreamBuilder(
stream: DatabaseService(uid: uid).userData,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Center(
child: CircleAvatar(
radius: 50,
backgroundImage: NetworkImage(snapshot.data!.photoUrl),
),
);
} else {
return CircularProgressIndicator();

Flutter: Weird listview/stream builder behavior

I have a home_page.dart file whose body has a StreamBuilder it recieves the stream from my getChats() function. In the StreamBuilder's builder function I sort the all the documents after storing them in a list named docsList based on the lastMessageTime field so that the document with the latest message is at the top (first).
As the ListView is using the docsList for building the cards it is expected that the document which has the most resent message should be displayed first. Which only happens when the list is build for the first time. After that if I send a new message to the chat which is not at the top this happens:
Initially:
When I send a message which the text 'test' to the chat "Heah Roger" this is how the list gets updated:
As it can be seen the Time on the right and the subtext changes for the first tile but the image and name didn't (same for second tile). Even though the documents are updated in the docsList and are sorted in the desired manner (I printed it to check it). Somehow the photo and the name alone are not being updated in the UI alone.
Note: The correct fields are updated in the firestore. Also if I restart the app after killing it. It shows the desired result:
getChats()
Stream<QuerySnapshot<Map<String, dynamic>>> getChats(User currentUser) {
return FirebaseFirestore.instance
.collection('chats')
.where('users', arrayContains: currentUser.id)
.snapshots();
}
home_page.dart
body: StreamBuilder(
stream: RepositoryProvider.of<FirestoreRepository>(context).getChats(BlocProvider.of<AuthenticationBloc>(context).state.user),
builder: (context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.hasData && snapshot.data.docs.length > 0) {
List docsList = snapshot.data.docs;
docsList.sort((a, b) => b.data()['lastMessageTime'].compareTo(a.data()['lastMessageTime']));
return ListView.builder(
itemCount: docsList.length,
itemBuilder: (context, index) {
return SingleChatCard(chatRoom: ChatRoomModel.fromMap(docsList[index].data()));
},
);
} else {
return ...
}
},
),
Can anyone help me figure out the underlying problem that is causing this weird behavior?
Looks like an key issue to me,
When you're using your custom Widget to render in a listview, with some complicate data flow,
Flutter react to these changes one level at a time:
You can refer: https://www.youtube.com/watch?v=kn0EOS-ZiIc
In your example, you can do something like this:
return SingleChatCard(
key: ValueKey(index),
chatRoom: ChatRoomModel.fromMap(docsList[index].data()));
},

How can I query another collection inside a streambuilder that queries a different collection?

I'm trying to query a document field from a different firestore collection than the one of the streambuilder. Right now, with the streambuilder I am able to query one of the documents i need, however I don't how i'm to query another collection in that same stream builder. I thought about using a global variable from another class where I had already queried the document I want but that didn't seem to work.
This is the stream builder
Container(
height: MediaQuery.of(context).size.height,
margin: EdgeInsets.only(top: 0),
padding: EdgeInsets.only(top: 0),
child: StreamBuilder(
stream: Firestore.instance
.collection('Tournaments')
.document('Fortnite Tournaments')
.collection('Fortnite Tourneys')
.document(docID)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return new Text("Loading");
}
var tourneyDetails = snapshot.data;
return ListView(
children: <Widget>[
..........
The collection i'm trying to query is called "users"
Why i need to query a field in a different collection is because i'm writing an if statement that needs both of the fields
if (int.parse("Field_i_am_trying_to_get_from_another_collection") > int.parse(tourneyDetails[ 'tourneycost']))
print('You have the money');
else {
print('You're broke');
}
That condition is going to be executed when the raised button is clicked. Essentially, My problem is that I am currently not sure how I can query the data from that other collection.
Not sure if i explained that well but comment if you need more context or code, Thanks.
You can use provider instead of creating global variable.
see Provider package: https://pub.dev/packages/provider
if the current user is the user you want, then you can take the current user data from firestore when the app is loading and provide the user to where you want to use.
see this article if you don't know what provider is:
Flutter StateManagement with Provider

Display Firestore map data in Flutter

I am building a password manager and I'm trying to save on Firestore reads by displaying data in Map. The idea is to have a document (for each password category) and have the passwords stored as maps in it. See example screenshots here:
The idea is that users click on each password (map) and the app takes them to the relevant one using indexes. I then want the data from each map to be sorted separately so that they can live in their own Text widgets. But I haven't seen any possibility of displaying map data in Flutter yet.
I've tried some of the examples from here but haven't been able to display the data from the map - https://github.com/fireship-io/flutter-base/blob/master/lib/main.dart
Any suggestions would be much appreciated.
new StreamBuilder(
stream: Firestore.instance
.collection('users')
.document(userDocSTRING.toString())
.collection(userPassSTRING.toString())
.snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
// If no data is present, display a waiting indicator to the user
// If Null, red screen displays
return Center(child: CircularProgressIndicator());
} else {
// Debug print for Ryan
// print(snapshot.data[0].data.toString());
return new ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot documentSnapshot =
snapshot.data.documents[index];
return ListTile(
leading: Container(
child: IconButton(
icon: Icon(Icons.content_copy),
color: lightCardCOLOR,
title: Text(documentSnapshot['Name']
As you can see from the code above, fetching fields from documents is easy enough but I don't want each password to have it's own document. I want a document to hold multiple Maps which corresponds to a password. So documentSnapshot['Name'] I want to be the name or value of a map
I'll suggest that your attempt to "save on Firestore reads" is making it more difficult for you to model and display the data. It also won't scale, since the maximum size of a document is 1MB. Consider storing each password in a different document to make this easier. Document reads are not really very expensive, and the Firebase SDK will cache them locally to avoid the cost of reads when queried.