Dart Streams: Single-Subscription vs. Broadcast
A single-subscription stream is a private channel for one listener; a broadcast stream is a public radio station for many. Use single-subscription for one-off data like a file download and broadcast for shared events like UI updates.
WHY IT EXISTS Dart needs to handle two different kinds of asynchronous event sequences. One is a process with a clear start and end for a single consumer, like reading a file. The other is a source of ongoing, independent events that multiple consumers might be interested in, like user interactions. Differentiating them prevents ambiguity and enforces correct usage patterns.
THE MENTAL MODEL A single-subscription stream is a direct, private data transfer. Imagine a file download: the data is meant for one recipient, and the stream starts when the download begins and stops when it's done. You wouldn't have two different parts of your app trying to consume the same raw file download stream. A broadcast stream is a public announcement system. Think of a global notification for 'user logged out.' Multiple widgets or services might need to react to this event, so the stream broadcasts it to any current listeners.
HOW IT WORKS A single-subscription stream, the default for async* functions, is lazy. It won't generate events until a listener is attached. Once a listener is attached, it's exclusively theirs. If that listener cancels, the stream is considered 'used' and cannot be listened to again. It's designed for a single, complete consumption of a sequence. A broadcast stream, often created via .asBroadcastStream(), fires events as soon as they are available, regardless of listeners. New listeners only receive events fired after they subscribe; they miss the history. Any number of listeners can subscribe and unsubscribe at will.
WHEN TO USE IT Use single-subscription streams for streaming large, contiguous data chunks like file I/O or network responses. Use broadcast streams for independent, sporadic events that multiple parts of an app might need to react to, such as UI events (button clicks) or global state management updates.
WHEN NOT TO USE IT Never use a single-subscription stream when multiple widgets need to react to the same event source; you'll get an error on the second listener. Don't use a broadcast stream for data that must be delivered reliably to one consumer; if no one is listening when the event fires, it's lost forever.
ONE CANONICAL EXAMPLE An async* function creates a single-subscription stream. If you call myAsyncStarFunction() and try to listen() to the returned stream twice, your app will throw a StateError. This happens even if the first listener has already cancelled its subscription. To allow multiple listeners, you must convert it: mySingleSubscriptionStream.asBroadcastStream(). Now, multiple listeners can subscribe without error.
Read the original → api.dart.dev
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.