I want to create a stream that can emit a single value to every subscriber, no matter when they subscribed.
Ideally, the following code should print out two 42
before done
, but none of the given approaches work.
void main() async {
final stream = createStream(42);
stream.listen(printValue);
await Future.delayed(Duration(seconds: 1));
stream.listen(printValue);
// Wait for everything to finish.
await Future.delayed(Duration(seconds: 1));
print('done');
}
Stream<int> createStream(int val) {
// Error: Stream has already been listened to.
// return Stream.value(val);
// Only gets one output
return Stream.value(val).asBroadcastStream();
}
void printValue(int val) {
print(val);
}
Desired output:
42
42
done
But Stream.value()
generates an error Stream has already been listened to.
. While .asBroadcastStream()
gives the wrong result.
Note: Answers using RxDart would be welcomed.
You can achieve the desired output by using a multi-subscription stream:
void main() async {
final stream = createStream(42);
stream.listen(printValue);
await Future.delayed(Duration(seconds: 1));
stream.listen(printValue);
// Wait for everything to finish.
await Future.delayed(Duration(seconds: 1));
print('done');
}
/// Returns a multi-subscription stream.
Stream<int> createStream(int val) => Stream.multi((streamController) {
streamController.add(val);
});
void printValue(int val) {
print(val);
}
The console output is listed below:
$ dart main.dart
42
42
done
Note: Another easy way to create a multi-subscription stream is by using the factory constructor Stream.fromIterable
:
/// Returns a multi-subscription stream that yields only `val`.
Stream<int> createStream(int val) => Stream.fromIterable([val]);