Home > Back-end >  How do I change Stream<List<T1>> to Stream<List<T2>> in Flutter
How do I change Stream<List<T1>> to Stream<List<T2>> in Flutter

Time:02-24

New to Flutter so be gentle...

I want to isolate a specific package from the rest of my app to minimise the spread of changes should the package need to be replaced.

The package in question provides a Stream<List<TYPE1>> and I want to provide a Stream<List<TYPE2>> where each TYPE2 item in my list is created from some properties of each corresponding TYPE1 item in the original list.

The resultant Stream<List<TYPE2>> will then be made available to the rest of the app by means of a StreamProvider.

Hope someone can point me in the right direction?

CodePudding user response:

Hopefully that will be of help:

void main() {
  final intsStream = Stream.fromIterable([
    [1, 2, 3],
    [4, 5, 6],
  ]);

  final mappedIntStream = intsStream.map(
    (list) => list
        .map(
          (number) => (number * 2).toString(),
        )
        .toList(),
  );

  mappedIntStream.forEach(
    (list) => print(
      "list contents: ${list}, first element type: ${list.first.runtimeType}",
    ),
  );
}

Basically, just use map method on stream, which will allow you to modify each list, and then use map on list so you can change list contents

CodePudding user response:

This is a very common use case that you can want to transfer an existing stream to another stream. For example, You have a stream of Int that you want to transform to String. The most general approach is to create a new stream that waits for events on the original stream and then outputs new events. Example:

void main() {
  Stream<List<int>> listGenerator(Duration interval, [int? maxCount]) async* {
    int i = 0;
    List<int> list = [];
    while (true) {
      await Future.delayed(interval);
      i  ;

      list.add(i);
      yield list;

      if (i == maxCount) break;
    }
  }

  // stream with Stream<List<TYPE1>>
  final stream = listGenerator(Duration(seconds: 3), 10);

  // define transformer
  Stream<List<String>> streamTransformer(Stream<List<int>> source) async* {
    await for (final chunk in source) {
      final list = <String>[];
      for (final item in chunk) {
        list.add('${item.toString()}_string'); // the conversion can happen here
      }
      yield list;
    }
  }

  // transform
  // stream with Stream<List<TYPE2>>
  final newStream = streamTransformer(stream);

  // print out put
  newStream.forEach(print);
}

For many common transformations, you can use Stream-supplied transforming methods such as map(), where(), expand(), and take().

If you take the example above, the easier way to transform would be

void main() {
  Stream<List<int>> listGenerator(Duration interval, [int? maxCount]) async* {
    int i = 0;
    List<int> list = [];
    while (true) {
      await Future.delayed(interval);
      i  ;

      list.add(i);
      yield list;

      if (i == maxCount) break;
    }
  }

  // stream with Stream<List<TYPE1>>
  final stream = listGenerator(Duration(seconds: 3), 10);

  final newStream = stream.map(
    (list) {
      return list.map(
        ((item) {
          return '${item}_string';
        }),
      ).toList();
    },
  );

  // print out put
  newStream.forEach(print);
}


So, your output would become in both cases

[1_string]
[1_string, 2_string]
[1_string, 2_string, 3_string]
[1_string, 2_string, 3_string, 4_string]
[1_string, 2_string, 3_string, 4_string, 5_string]
[1_string, 2_string, 3_string, 4_string, 5_string, 6_string]
[1_string, 2_string, 3_string, 4_string, 5_string, 6_string, 7_string]
[1_string, 2_string, 3_string, 4_string, 5_string, 6_string, 7_string, 8_string]
[1_string, 2_string, 3_string, 4_string, 5_string, 6_string, 7_string, 8_string, 9_string]
[1_string, 2_string, 3_string, 4_string, 5_string, 6_string, 7_string, 8_string, 9_string, 10_string]

  • Related