tezvyn:

Dart's Stream: Asynchronous Data Pipelines

AI-drafted, machine-checkedSource: api.dart.devintermediate

Think of a Dart Stream as a conveyor belt for asynchronous data, delivering events over time. It's ideal for handling sequences like user input or file I/O.

WHY IT EXISTS: Many operations don't complete at once. They produce data over time, like reading a file or receiving network packets. A Future handles a single asynchronous result, but we need a way to represent a sequence of asynchronous events. The Stream class was created to be the asynchronous equivalent of an Iterable.

THE MENTAL MODEL: Think of a Stream as a conveyor belt for data that arrives over time. Instead of getting a whole collection at once, you receive items one by one as they are produced. The belt can deliver data items, signal an error if something breaks, and finally send a "done" event when production stops. The stream itself does nothing until someone starts watching the belt.

HOW IT WORKS: A Stream is a source of asynchronous events. You typically create one by defining an async* function, which returns a Stream. This function remains dormant until a listener subscribes, usually with an await for loop or the .listen() method. Once a listener is attached, the async* function's body begins to execute, using yield to push data events into the stream. When the function finishes, a "done" event is sent and the stream closes. If an error is thrown, it's emitted as an error event. The connection between a listener and a stream is managed by a StreamSubscription object, which allows you to pause, resume, or cancel the flow of events.

WHEN TO USE IT: Streams are fundamental to reactive programming in Dart. There are two types. First, use a single-subscription stream for streaming large, contiguous data to a single consumer, like reading a file or handling an HTTP response body. Second, use a broadcast stream for events that might have multiple interested listeners, like user interface actions (button clicks) or global state changes. You can convert a single-subscription stream to a broadcast one using .asBroadcastStream().

WHEN NOT TO USE IT: If you only need a single value from an asynchronous operation, use a Future. Using a Stream to emit just one value and then immediately close is overly complex. A Future is purpose-built for a one-time result and is simpler to work with in that context.

ONE CANONICAL EXAMPLE: The two stream types are the most critical distinction. A single-subscription stream is like a ticket to a movie screening. Only one person can use it, and they watch the film from start to finish. You can't have a second person use the same ticket, even if the first person leaves early. A broadcast stream is like a radio station. Anyone can tune in at any time to hear what's currently being broadcast, and multiple listeners can tune in simultaneously without interfering with each other.

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.