Dart Streams: Asynchronous Data Sequences
A Dart Stream is like a conveyor belt for asynchronous data, delivering events or file chunks as they arrive. Use them for continuous data flows like button clicks or reading large files.
WHY IT EXISTS While a Future represents a single value that will be available later, many asynchronous operations involve a sequence of values over time. Dart needed a way to represent these asynchronous sequences, like ongoing user input or data arriving in chunks over a network.
THE MENTAL MODEL A Future is like waiting for a single package to be delivered. A Stream is the entire conveyor belt, bringing a series of packages over time. You subscribe to the stream to process each package as it arrives, and you can also handle errors if a package is damaged or the belt breaks.
HOW IT WORKS You consume a stream in two primary ways. The first is with an await for loop, which lets you process each event in a way that looks like a synchronous for loop. The second is by calling the .listen() method on the stream directly. This provides callbacks for handling data events (onData), errors (onError), and the stream's completion (onDone). Streams can also be transformed, creating a new stream from an old one, for example, by filtering or mapping events.
WHEN TO USE IT Use streams for any sequence of asynchronous events. This is common in Flutter for listening to UI events like button presses, tracking authentication state changes from a service like Firebase, or receiving data from a WebSocket. They are also ideal for reading large files from disk without loading the entire file into memory at once.
WHEN NOT TO USE IT If you only need a single asynchronous value, a Future is simpler and more appropriate. Using a stream for a one-off network request that returns a single JSON object is overkill; a Future is the correct tool for that job.
ONE CANONICAL EXAMPLE Streams come in two flavors. A single-subscription stream is for a sequence that is consumed in its entirety by one listener, like reading a file. It will buffer data until a listener subscribes. A broadcast stream is for events that can have multiple listeners, like a stream of button clicks. It fires events as they happen, and new listeners won't receive past events. A common footgun is trying to listen to a single-subscription stream more than once, which will throw a runtime error.
Read the original → 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.