Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dart: how to append a transformer to an existing stream?

I'm looking a for a way to programmatically add a transformer to an existing stream that's already being listen to.

Example:

Stream numbers = new Stream.fromIterable([0,1,2,3]);

numbers.listen((number) => print(number));

Now in response to some UI event, I'd like to modify this stream by adding a mapping transformer, as if I originally wrote:

numbers.where((number) => number % 2 == 0);

All existing listeners should from now own only receive even numbers, without interruption. How can this be done?

like image 888
sms1 Avatar asked Sep 18 '14 00:09

sms1


People also ask

How do I add data to stream flutter?

add("Data!"); With a StreamController instance, you can access a stream to listen for and react to data events using the Stream instance's listen() method, and you can access a sink to add new data events to the stream using the add() method of EventSink.

What is StreamSubscription?

A subscription on events from a Stream. When you listen on a Stream using Stream. listen, a StreamSubscription object is returned. The subscription provides events to the listener, and holds the callbacks used to handle the events.

What is StreamTransformer in flutter?

StreamTransformer<S, T> class Null safety. Transforms a Stream. When a stream's Stream. transform method is invoked with a StreamTransformer, the stream calls the bind method on the provided transformer. The resulting stream is then returned from the Stream.

What is asynchronous stream?

An asynchronous data stream is a stream of data where values are emitted, one after another, with a delay between them. The word asynchronous means that the data emitted can appear anywhere in time, after one second or even after two minutes, for example.


2 Answers

Instead of thinking about it like "how do I dynamically insert a transformer into a stream", one possible way is to think about it like "how do I dynamically control a transformer that I already injected".

Here's an example of using a StreamTransformer:

var onlySendEvenNumbers = false; // controlled by some UI event handler

var originalStream = makeStreamOfStuff();

originalStream = originalStream.transform(new StreamTransformer.fromHandlers(
  handleData: (int value, EventSink<int> sink) {
    if (onlySendEvenNumber) {
      if (value.isEven) {
        sink.add(value);
      }
    } else {
      sink.add(value);
    }
}));

originalStream.listen(print);  // listen on events like normal
like image 183
Seth Ladd Avatar answered Sep 21 '22 12:09

Seth Ladd


One way I can think of doing that is filtering the Stream with a function that calls another function:

var filter = (n) => true;
Stream numbers = new String.fromIterable([0, 1, 2, 3]).where((n) => filter(n));

Then, when you want to change the filtering:

filter = (n) => n % 2 == 0;

A concrete example:

import 'dart:async';

main() {
  var filter = (n) => true;

  Stream numbers = new Stream.periodic(new Duration(seconds: 1), (n) => n)
      .where((n) => filter(n));

  numbers.listen((n) => print(n));

  new Future.delayed(new Duration(seconds: 4)).then((_) {
    filter = (n) => n % 2 == 0;
  });
}

This will print:

0
1
2
3
4
6
8
10
12

And so on, for even numbers only, after 4 seconds.

like image 42
Tonio Avatar answered Sep 23 '22 12:09

Tonio