A stream controller that delivers its events synchronously.
A synchronous stream controller is intended for cases where an already asynchronous event triggers an event on a stream.
Instead of adding the event to the stream in a later microtask, causing extra latency, the event is instead fired immediately by the synchronous stream controller, as if the stream event was the current event or microtask.
The synchronous stream controller can be used to break the contract on Stream, and it must be used carefully to avoid doing so.
The only advantage to using a SynchronousStreamController over a normal StreamController is the improved latency. Only use the synchronous version if the improvement is significant, and if its use is safe. Otherwise just use a normal stream controller, which will always have the correct behavior for a Stream, and won't accidentally break other code.
Adding events to a synchronous controller should only happen as the very last part of the handling of the original event. At that point, adding an event to the stream is equivalent to returning to the event loop and adding the event in the next microtask.
Each listener callback will be run as if it was a top-level event or microtask. This means that if it throws, the error will be reported as uncaught as soon as possible. This is one reason to add the event as the last thing in the original event handler – any action done after adding the event will delay the report of errors in the event listener callbacks.
If an event is added in a setting that isn't known to be another event, it may cause the stream's listener to get that event before the listener is ready to handle it. We promise that after calling Stream.listen, you won't get any events until the code doing the listen has completed. Calling add in response to a function call of unknown origin may break that promise.
An onListen callback from the controller is not an asynchronous event,
and adding events to the controller in the onListen
callback is always
wrong. The events will be delivered before the listener has even received
the subscription yet.
The synchronous broadcast stream controller also has a restrictions that a normal stream controller does not: The add, addError, close and addStream methods must not be called while an event is being delivered. That is, if a callback on a subscription on the controller's stream causes a call to any of the functions above, the call will fail. A broadcast stream may have more than one listener, and if an event is added synchronously while another is being also in the process of being added, the latter event might reach some listeners before the former. To prevent that, an event cannot be added while a previous event is being fired. This guarantees that an event is fully delivered when the first add, addError or close returns, and further events will be delivered in the correct order.
This still only guarantees that the event is delivered to the subscription. If the subscription is paused, the actual callback may still happen later, and the event will instead be buffered by the subscription. Barring pausing, and the following buffered events that haven't been delivered yet, callbacks will be called synchronously when an event is added.
Adding an event to a synchronous non-broadcast stream controller while another event is in progress may cause the second event to be delayed and not be delivered synchronously, and until that event is delivered, the controller will not act synchronously.
- Implemented types
Properties
- done → Future
-
A future which is completed when the stream controller is done
sending events.
no setterinherited
- hashCode → int
-
The hash code for this object.
no setterinherited
- hasListener → bool
-
Whether there is a subscriber on the Stream.
no setterinherited
- isClosed → bool
-
Whether the stream controller is closed for adding more events.
no setterinherited
- isPaused → bool
-
Whether the subscription would need to buffer events.
no setterinherited
-
onCancel
↔ FutureOr<
void> Function()? -
The callback which is called when the stream is canceled.
getter/setter pairinherited
- onListen ↔ void Function()?
-
The callback which is called when the stream is listened to.
getter/setter pairinherited
- onPause ↔ void Function()?
-
The callback which is called when the stream is paused.
getter/setter pairinherited
- onResume ↔ void Function()?
-
The callback which is called when the stream is resumed.
getter/setter pairinherited
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
-
sink
→ StreamSink<
T> -
Returns a view of this object that only exposes the StreamSink interface.
no setterinherited
-
stream
→ Stream<
T> -
The stream that this controller is controlling.
no setterinherited
Methods
-
add(
T data) → void -
Adds event to the controller's stream.
override
-
addError(
Object error, [StackTrace? stackTrace]) → void -
Adds error to the controller's stream.
override
-
addStream(
Stream< T> source, {bool? cancelOnError}) → Future -
Receives events from
source
and puts them into this controller's stream.inherited -
close(
) → Future -
Closes the controller's stream.
override
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited