I'm using streams to monitor changes in my firestore backend. That works all right for updates, but I do not get the initial value.
class A {
final Stream<DocumentSnapshot> _visitorCount =
Firestore.instance.document('ServerData/serverStatus').snapshots();
Stream<int> get visitorCount {
return Observable(_visitorCount)
.map((DocumentSnapshot doc) => doc['activeUsers'] as int);
}
}
I could use rxdart
's startWith
to provide an initial value, but reading out this value results in a Future<int>
and I'd need to supply an int
to startWith
.
static Future<int> f = Firestore.instance
.collection('ServerData')
.document('serverStatus')
.get()
.then((doc) => doc['activeUsers'] as int);
down the road I use it like this:
StreamBuilder(
stream: _visitorCount,
initialData: 0,
builder: (context, snapshot) =>
Text('${snapshot.data} users logged in') ...
I provide 0
as initial value but this is of course just a temporary value.
I'm sure this is so obvious but still I struggle to get it right.
What's the best way to solve this?
Turns out the problem I needed to solve did not require me to add some value from a future into the stream to make up for missed values. All I needed is to use a BehaviorSubject
as pointed out by Remi Rousselet.
But for completeness: here is how you take a value from a Future
and push it into a stream:
Future
into a streamclass A {
Subject<int> _stateSubject;
Subject<int> _state;
Subject<int> get state {
return _state;
}
A() {
_stateSubject = new BehaviorSubject();
_state = _stateSubject;
Firestore.instance
.document('ServerData/serverStatus')
.snapshots()
.map((DocumentSnapshot doc) => doc['activeUsers'] as int)
.listen((int value) {
_stateSubject.add(value);
});
}
Future<int> get visitorCount => Firestore.instance
.document('ServerData/serverStatus')
.get()
.then((DocumentSnapshot d) => d.data['activeUsers']);
void addFromFuture() => visitorCount.then((int v) => _state.add(v + 1));
}
By calling addFromFuture
I can query some value that will result in a Future<int>
, take this value and push it into the Subject
with the add()
function. All the listeners to the _state
-Subject
will receive those updates.
BehaviorSubject
easier?As an explanation why BehaviorSubject
saves us from using this awkward workaround with Future
s (taken from the RxJava docs):
Even though another subscriber came in late, the most recent received item is buffered and delivered correctly.