How to listen firebase updates in real time in Flutter
Solution 1
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.
Solution 2
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).
wierdo
Updated on November 28, 2022Comments
-
wierdo over 1 year
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; }
-
Gazihan Alankus almost 4 yearsI think
print
won't execute after a modification to the database becauseawait for
gets the first state of the database and quits, because of thereturn
statement in it. -
wierdo almost 4 yearsyes, print won't execute after data update. But when I don't return currentUser in await, it returns nothing. What is the most appropriate way to return the currentUser?
-
Gazihan Alankus almost 4 yearsyou just should not return anything. you should "get it done" in this function using setState. If you want to return values again and again, your function would need to return a Stream (you can do this easily with async* and yield) but it defeats the purpose, you already have a Stream by calling .snapshots(). So, you should either restructre your app to use StreamBuilder or call setState in this function.
-
wierdo almost 4 yearsthanks, I converted it to a void function. And handle UI side with a StreamBuilder. Now it updates data instantly.