toBroadcastStream method
Convert a channel receiver to a broadcast stream for multiple listeners.
Perfect for integrating channels with Flutter widgets that expect broadcast streams, or when multiple components need to listen to the same channel data.
Parameters:
waitForListeners: Iftrue, doesn't start consuming until first listenerstopWhenNoListeners: Iftrue, pauses consumption when no listenerscloseReceiverOnDone: Iftrue, closes the receiver when stream endssync: Iftrue, events are delivered synchronously
Usage: {@tool snippet example/stream_to_broadcast.dart} {@end-tool}
Implementation
Stream<T> toBroadcastStream({
bool waitForListeners = false,
bool stopWhenNoListeners = true,
bool closeReceiverOnDone = false,
bool sync = false,
}) {
final source = stream();
StreamSubscription<T>? sub;
late final StreamController<T> ctrl;
final bool shouldPause = waitForListeners && stopWhenNoListeners;
void startIfNeeded() {
if (sub != null) return;
sub = source.listen(
(v) => ctrl.add(v),
onError: ctrl.addError,
onDone: () async {
if (closeReceiverOnDone && !recvDisconnected) close();
await ctrl.close();
},
cancelOnError: false,
);
if (shouldPause && !ctrl.hasListener) {
sub!.pause();
}
}
Future<void> pauseIfNeeded() async {
final s = sub;
if (s != null && !s.isPaused) s.pause();
}
Future<void> resumeIfNeeded() async {
final s = sub;
if (s != null && s.isPaused) s.resume();
}
ctrl = StreamController<T>.broadcast(
sync: sync,
onListen: () {
startIfNeeded();
if (shouldPause) resumeIfNeeded();
},
onCancel: () async {
if (shouldPause && !ctrl.hasListener) {
return pauseIfNeeded();
}
return;
},
);
if (!waitForListeners) {
startIfNeeded();
}
return ctrl.stream;
}