Flutter cloud firestore not updating automatically - firebase

I try to read listen to a stream from Firebase with this code:
visibleListsIds.forEach((final String listId) async {
final Stream<List<WishList>> wishListStream = sharedCollection()
.document(listId)
.snapshots()
.map((DocumentSnapshot documentSnapshot) {
log.d("updated Document Snapshot: ${documentSnapshot.data}");
return [
_getSerializers()
.deserializeWith(WishList.serializer, documentSnapshot.data)
];
});
wishListStreams.add(wishListStream);
});
Where sharedCollection() gives me access to the Firestore instance with the correct collection
I try to write to the collection, with this code
DocumentReference postRef = sharedCollection().document(wishList.listId);
firestore.runTransaction((Transaction tx) async {
DocumentSnapshot postSnapshot = await tx.get(postRef);
if (postSnapshot.exists) {
await tx.update(postRef,
_getSerializers().serializeWith(WishList.serializer, wishList));
} else {
await tx.set(postRef,
_getSerializers().serializeWith(WishList.serializer, wishList));
}
});
What happens:
I can write to Firebase but only one change at a time. When I do the next update, the last one gets reverted.
I can see the updated data only in the Firebase Console. The App does not show it and it does not show in the log at log.d("updated Document Snapshot: ${documentSnapshot.data}");.
When I modify data in the Firebase Console, I can also not see it change
BUT once I reload the App, all the Data syncs up to the current state of the Firebase Console
Anyone know why I do not get updates with the Stream?
Thanks for your help.
I use the Cloud Firestore Plugin:
cloud_firestore: ^0.13.0+1

Related

How to read data from Firebase Realtime database using Flutter/Dart

I am using Flutter and I would like to retrieve some data from my realtime database Firebase. I have the following data stored in the my realtime database Firebase:
How can I get each piece of information from it? For example I would like to get the name 'Tom' only?
Reading through firebase documentation you can see that how we read and write data from RTDMS firebase.
static Future<List<PostModel>> getPost() async {
Query postsSnapshot = await FirebaseDatabase.instance
.reference()
.child("posts")
.orderByKey();
print(postsSnapshot); // to debug and see if data is returned
List<PostModel> posts;
Map<dynamic, dynamic> values = postsSnapshot.data.value;
values.forEach((key, values) {
posts.add(values);
});
return posts;
}
your can call this function at the time of build the widget or after any action
FirebaseDatabase.instance.ref("users").onValue.listen((event) {
final data =
Map<String, dynamic>.from(event.snapshot.value as Map,);
data.forEach((key, value) {
log("$value");
});
});

Flutter Firebase DocumentReference.set() is not completing

My application was writing to Firestore but suddenly stopped working. When I try to write to Firestore my write method does not complete. I have made the following simple test method to troubleshoot my problem but can't seem to figure out what is going on:
//In database.dart
Future<void> testSet() async {
final reference = FirebaseFirestore.instance.doc('users/test');
await reference.set({'TEST': 'Value'});
print('This is never printing');
}
//In home_page.dart called via clicking a button
Future<void> _testSet(context) async {
final database = Provider.of<Database>(context, listen: false);
await database.testSet();
}
I have tried emptying my Firestore Database as well as adding a users collection; however nothing has worked. Why am I unable to write to Firestore?

How do I index queries in Firebase?

I'm trying to get documents that contain location fields that match with the user's location using:
getLocationListings(placemark) async {
setState(() {
isLoading = true;
});
QuerySnapshot snapshot = await FirebaseFirestore.instance
.collectionGroup("posts")
.where('location', isGreaterThanOrEqualTo: placemark.locality)
.get();
setState(() {
posts = snapshot.docs.map((doc) => Post.fromDocument(doc)).toList();
isLoading = false;
});
}
I'm getting the error:
Operation was rejected because the system is not in a state required for the operation's execution. If performing a query, ensure it has been indexed via the Firebase console.
Yet I have created indexes at the console as
How can I correct this?
Something might be wrong in the indexes you created for that collection group. I would recommend you to delete the index you created and run the function again, it's going to throw an error and if you were to check android device logs by executing
adb logcat
on the terminal you will see a message like this:
'FAILED_PRECONDITION: The query requires an index. You can create it here: https://console.firebase.google.com/v1/r/project/XXXXXXXXX/firestore/indexes?create_composite=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'.
Just click on the link and create the proposed index, this should fix the issue.

Deleting docs in cloud Firestore

I'm trying to code a todo App linked with cloud firestore. I want that when i tap on my tile which is a Gesture Detector, the task is deleted on firestore but it won't work.
Here's my code for my Function i use and all things that are necessary.
final _firestore = FirebaseFirestore.instance;
///
void deleteTask(){
_firestore.collection("todos").doc().delete();
}
///
child: GestureDetector(
onLongPress: (){
deleteTask();
},
child: Container(
When you are setting new doc Firebase probably this kind of code you use:
var db = FirebaseFirestore.instance;
DocumentReference ref = db.collection('tasks').doc();
ref.set(
{'field': data},
);
// save your ref.id here in order to let user remove the task eventually
This piece of code you wrote just puts a new document on a field. Now when you create or populate your Task class, you need to obtain document ID in order to delete it.
removeTask(String documentID) async {
var db = FirebaseFirestore.instance;
DocumentReference ref = db.collection('tasks').doc(documentID);
ref.delete();
}
// ref.id gives you the doc ID. Put it in your Task class when fetching docs
// so if user wants to delete any document, he/she can delete it.

How to listen firebase updates in real time in Flutter

I have a stream which read user data from firebase. I trigger it after signin, it works perfectly. I show the data in my appbar. When I update firebase manually, I want to see the new date instantly on my appbar. First, I guessed there is something wrong with my appbar but then I noticed that my stream do not triggered when I update firebase data. Here is my stream code snippet. What am I missing?
static Future<User> userDataStream(userID) async {
print("userDataStream");
final databaseReference = Firestore.instance;
User currentUser = User();
await for (var snapshot in databaseReference
.collection('users')
.where('userID', isEqualTo: userID)
.snapshots()) {
currentUser.userName = snapshot.documents.first.data['userName'];
currentUser.email = snapshot.documents.first.data['email'];
currentUser.userID = snapshot.documents.first.data['userID'];
currentUser.level = snapshot.documents.first.data['level'];
currentUser.balance = snapshot.documents.first.data['balance'];
print(currentUser.balance);
return currentUser;
}
return currentUser;
}
How you are using this stream matters. await for starts listening to the user, then you do return currentUser; in it and break the await for. Therefore, it cannot keep listening to the stream in the future.
Instead of the return currentUser; inside await for, you can do something like setState((){this.renderedUser = currentUser;}) so that the user that comes from the server becomes the rendered one. If you do that, also add if (!mounted) return; inside the await for so that you stop listening to it when you realize you are in a different screen.
A better alternative may be to use the StreamBuilder widget.
If you run your current code, and make a change to the database, the print statement should be run again. That's because the snapshots is already listening for changes to the database, and calling your code when those happens.
The problem is that you return a Future<User> and a future can only be resolved (get a value) once. If you want to return live data that'd be a Stream<User> (and typically a StreamBuilder instead of a FutureBuilder to build a UI from it).

Resources