StreamTransformer<S, T>.fromHandlers constructor

StreamTransformer<S, T>.fromHandlers({
  1. void handleData(
    1. S data,
    2. EventSink<T> sink
    )?,
  2. void handleError(
    1. Object error,
    2. StackTrace stackTrace,
    3. EventSink<T> sink
    )?,
  3. void handleDone(
    1. EventSink<T> sink
    )?,
})

Creates a StreamTransformer that delegates events to the given functions.

Example use of a duplicating transformer:

stringStream.transform(StreamTransformer<String, String>.fromHandlers(
    handleData: (String value, EventSink<String> sink) {
      sink.add(value);
      sink.add(value);  // Duplicate the incoming events.
    }));

When a transformed stream returned from a call to bind is listened to, the source stream is listened to, and a handler function is called for each event of the source stream.

The handlers are invoked with the event data and with a sink that can be used to emit events on the transformed stream.

The handleData handler is invoked for data events on the source stream. If handleData was omitted, data events are added directly to the created stream, as if calling EventSink.add on the sink with the event value. If handleData is omitted the source stream event type, S, must be a subtype of the transformed stream event type T.

The handleError handler is invoked for each error of the source stream. If handleError is omitted, errors are forwarded directly to the transformed stream, as if calling EventSink.addError with the error and stack trace.

The handleDone handler is invoked when the source stream closes, as signaled by sending a done event. The done handler takes no event value, but can still send other events before calling EventSink.close. If handleDone is omitted, a done event on the source stream closes the transformed stream.

If any handler calls EventSink.close on the provided sink, the transformed sink closes and the source stream subscription is cancelled. No further events can be added to the sink by that handler, and no further source stream events will occur.

The sink provided to the event handlers must only be used during the call to that handler. It must not be stored and used at a later time.

Transformers created this way should be stateless. They should not retain state between invocations of handlers, because the same transformer, and therefore the same handlers, may be used on multiple streams, or on streams which can be listened to more than once. To create per-stream handlers, StreamTransformer.fromBind could be used to create a new StreamTransformer.fromHandlers per stream to transform.

var controller = StreamController<String>.broadcast();
controller.onListen = () {
  scheduleMicrotask(() {
    controller.addError("Bad");
    controller.addError("Worse");
    controller.addError("Worst");
  });
};
var sharedState = 0;
var transformedStream = controller.stream.transform(
    StreamTransformer<String>.fromHandlers(
        handleError: (error, stackTrace, sink) {
  sharedState++; // Increment shared error-counter.
  sink.add("Error $sharedState: $error");
}));

transformedStream.listen(print);
transformedStream.listen(print); // Listen twice.
// Listening twice to the same stream makes the transformer share the same
// state. Instead of having "Error 1: Bad", "Error 2: Worse",
// "Error 3: Worst" as output (each twice for the separate subscriptions),
// this program emits:
// Error 1: Bad
// Error 2: Bad
// Error 3: Worse
// Error 4: Worse
// Error 5: Worst
// Error 6: Worst

Implementation

factory StreamTransformer.fromHandlers(
    {void handleData(S data, EventSink<T> sink)?,
    void handleError(Object error, StackTrace stackTrace, EventSink<T> sink)?,
    void handleDone(EventSink<T> sink)?}) = _StreamHandlerTransformer<S, T>;