Appearance
SynchronousStreamController<T> abstract interface
abstract interface class SynchronousStreamController<T> implements StreamController<T>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 no setter inherited
Future<dynamic> get doneA future which is completed when the stream controller is done sending events.
This happens either when the done event has been sent, or if the subscriber on a single-subscription stream is canceled.
A stream controller will not complete the returned future until all listeners present when the done event is sent have stopped listening. A listener will stop listening if it is cancelled, or if it has handled the done event. A paused listener will not process the done even until it is resumed, so completion of the returned Future will be delayed until all paused listeners have been resumed or cancelled.
If there is no listener on a non-broadcast stream, or the listener pauses and never resumes, the done event will not be sent and this future will never complete.
Inherited from StreamController.
Implementation
dart
Future get done;hashCode no setter inherited
int get hashCodeThe hash code for this object.
A hash code is a single integer which represents the state of the object that affects operator == comparisons.
All objects have hash codes. The default hash code implemented by Object represents only the identity of the object, the same way as the default operator == implementation only considers objects equal if they are identical (see identityHashCode).
If operator == is overridden to use the object state instead, the hash code must also be changed to represent that state, otherwise the object cannot be used in hash based data structures like the default Set and Map implementations.
Hash codes must be the same for objects that are equal to each other according to operator ==. The hash code of an object should only change if the object changes in a way that affects equality. There are no further requirements for the hash codes. They need not be consistent between executions of the same program and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code. It is even technically allowed that all instances have the same hash code, but if clashes happen too often, it may reduce the efficiency of hash-based data structures like HashSet or HashMap.
If a subclass overrides hashCode, it should override the operator == operator as well to maintain consistency.
Inherited from Object.
Implementation
dart
external int get hashCode;hasListener no setter inherited
bool get hasListenerWhether there is a subscriber on the Stream.
Inherited from StreamController.
Implementation
dart
bool get hasListener;isClosed no setter inherited
bool get isClosedWhether the stream controller is closed for adding more events.
The controller becomes closed by calling the close method. New events cannot be added, by calling add or addError, to a closed controller.
If the controller is closed, the "done" event might not have been delivered yet, but it has been scheduled, and it is too late to add more events.
Inherited from StreamController.
Implementation
dart
bool get isClosed;isPaused no setter inherited
bool get isPausedWhether the subscription would need to buffer events.
This is the case if the controller's stream has a listener and it is paused, or if it has not received a listener yet. In that case, the controller is considered paused as well.
A broadcast stream controller is never considered paused. It always forwards its events to all uncanceled subscriptions, if any, and let the subscriptions handle their own pausing and buffering.
Inherited from StreamController.
Implementation
dart
bool get isPaused;onCancel read / write inherited
(FutureOr<void> Function())? onCancelgetter:
The callback which is called when the stream is canceled.
May be set to null, in which case no callback will happen.
setter:
The callback which is called when the stream is canceled.
May be set to null, in which case no callback will happen.
Inherited from StreamController.
Implementation
dart
abstract FutureOr<void> Function()? onCancel;onListen read / write inherited
(void Function())? onListengetter:
The callback which is called when the stream is listened to.
May be set to null, in which case no callback will happen.
setter:
The callback which is called when the stream is listened to.
May be set to null, in which case no callback will happen.
Inherited from StreamController.
Implementation
dart
abstract void Function()? onListen;onPause read / write inherited
(void Function())? onPausegetter:
The callback which is called when the stream is paused.
May be set to null, in which case no callback will happen.
Pause related callbacks are not supported on broadcast stream controllers.
setter:
The callback which is called when the stream is paused.
May be set to null, in which case no callback will happen.
Pause related callbacks are not supported on broadcast stream controllers.
Inherited from StreamController.
Implementation
dart
abstract void Function()? onPause;onResume read / write inherited
(void Function())? onResumegetter:
The callback which is called when the stream is resumed.
May be set to null, in which case no callback will happen.
Pause related callbacks are not supported on broadcast stream controllers.
setter:
The callback which is called when the stream is resumed.
May be set to null, in which case no callback will happen.
Pause related callbacks are not supported on broadcast stream controllers.
Inherited from StreamController.
Implementation
dart
abstract void Function()? onResume;runtimeType no setter inherited
Type get runtimeTypeA representation of the runtime type of the object.
Inherited from Object.
Implementation
dart
external Type get runtimeType;sink no setter inherited
StreamSink<T> get sinkReturns a view of this object that only exposes the StreamSink interface.
Inherited from StreamController.
Implementation
dart
StreamSink<T> get sink;stream no setter inherited
Stream<T> get streamThe stream that this controller is controlling.
Inherited from StreamController.
Implementation
dart
Stream<T> get stream;Methods
add() override
void add(T data)Adds event to the controller's stream.
As StreamController.add, but must not be called while an event is being added by add, addError or close.
Implementation
dart
void add(T data);addError() override
void addError(Object error, [StackTrace? stackTrace])Adds error to the controller's stream.
As StreamController.addError, but must not be called while an event is being added by add, addError or close.
Implementation
dart
void addError(Object error, [StackTrace? stackTrace]);addStream() inherited
Receives events from source and puts them into this controller's stream.
Returns a future which completes when the source stream is done.
Events must not be added directly to this controller using add, addError, close or addStream, until the returned future is complete.
Data and error events are forwarded to this controller's stream. A done event on the source will end the addStream operation and complete the returned future.
If cancelOnError is true, only the first error on source is forwarded to the controller's stream, and the addStream ends after this. If cancelOnError is false, all errors are forwarded and only a done event will end the addStream. If cancelOnError is omitted or null, it defaults to false.
Inherited from StreamController.
Implementation
dart
Future addStream(Stream<T> source, {bool? cancelOnError});close() override
Future<dynamic> close()Closes the controller's stream.
As StreamController.close, but must not be called while an event is being added by add, addError or close.
Implementation
dart
Future close();noSuchMethod() inherited
dynamic noSuchMethod(Invocation invocation)Invoked when a nonexistent method or property is accessed.
A dynamic member invocation can attempt to call a member which doesn't exist on the receiving object. Example:
dart
dynamic object = 1;
object.add(42); // Statically allowed, run-time errorThis invalid code will invoke the noSuchMethod method of the integer 1 with an Invocation representing the .add(42) call and arguments (which then throws).
Classes can override noSuchMethod to provide custom behavior for such invalid dynamic invocations.
A class with a non-default noSuchMethod invocation can also omit implementations for members of its interface. Example:
dart
class MockList<T> implements List<T> {
noSuchMethod(Invocation invocation) {
log(invocation);
super.noSuchMethod(invocation); // Will throw.
}
}
void main() {
MockList().add(42);
}This code has no compile-time warnings or errors even though the MockList class has no concrete implementation of any of the List interface methods. Calls to List methods are forwarded to noSuchMethod, so this code will log an invocation similar to Invocation.method(#add, [42]) and then throw.
If a value is returned from noSuchMethod, it becomes the result of the original invocation. If the value is not of a type that can be returned by the original invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError.
Inherited from Object.
Implementation
dart
@pragma("vm:entry-point")
@pragma("wasm:entry-point")
external dynamic noSuchMethod(Invocation invocation);toString() inherited
String toString()A string representation of this object.
Some classes have a default textual representation, often paired with a static parse function (like int.parse). These classes will provide the textual representation as their string representation.
Other classes have no meaningful textual representation that a program will care about. Such classes will typically override toString to provide useful information when inspecting the object, mainly for debugging or logging.
Inherited from Object.
Implementation
dart
external String toString();Operators
operator ==() inherited
The equality operator.
The default behavior for all Objects is to return true if and only if this object and other are the same object.
Override this method to specify a different equality relation on a class. The overriding method must still be an equivalence relation. That is, it must be:
Total: It must return a boolean for all arguments. It should never throw.
Reflexive: For all objects
o,o == omust be true.Symmetric: For all objects
o1ando2,o1 == o2ando2 == o1must either both be true, or both be false.Transitive: For all objects
o1,o2, ando3, ifo1 == o2ando2 == o3are true, theno1 == o3must be true.
The method should also be consistent over time, so whether two objects are equal should only change if at least one of the objects was modified.
If a subclass overrides the equality operator, it should override the hashCode method as well to maintain consistency.
Inherited from Object.
Implementation
dart
external bool operator ==(Object other);