RxDart, mapping each item of a list to another object coming from a never ending stream

Issue

I’ve been trying to find a nice way of doing this but I had no luck.

Here is a simplified version of the problem:

import 'package:rxdart/rxdart.dart';


/// Input a list of integers [0,1,2,3,4]
/// map each of those integers to the corresponding index in the map
/// if the map updates, the output should update too.
///
/// The output should be a list of Strings:
/// ["Hi from 1", "Hi from 2"; "Hi from 3", "Hi from 4", "Hi from 5"]
BehaviorSubject<Map<int, String>> subject = BehaviorSubject(
    seedValue: {
      1: "Hi from 1",
      2: "Hi from 2",
      3: "Hi from 3",
      4: "Hi from 4",
      5: "Hi from 5",
    }
);

void main() {
  Observable.fromIterable([1, 2, 3, 4, 5])
      .flatMap((index) => subject.stream.map((map) => map[index]))
      .toList().asObservable()
      .listen((data) {
    print("List of data incoming $data");
  });
}

When running this, nothing is printed. This is because the subject never completes and thus the toList() never finishes building the list.

Replacing the subject with for example an Observable.just(index + 2) does work because the Observable completes and the toList() is able to collect them.

But the intended behavior is that the example should emit the new list of strings each time the subject is changed.

Any help would be appreciated,

Thanks!

Solution

You probably want to use combineLatest instead

BehaviorSubject<Map<int, String>> subject = BehaviorSubject(seedValue: {
  1: "Hi from 1",
  2: "Hi from 2",
  3: "Hi from 3",
  4: "Hi from 4",
  5: "Hi from 5",
});

void main() {
  Observable.combineLatest2(
      Observable.just([1, 2, 3, 4, 5]), subject.stream, combiner)
    ..listen(
      (data) {
        print("List of data incoming $data");
      },
    );
}

Iterable<String> combiner(List<int> indexes, Map<int, String> map) {
  return indexes.map((index) => map[index]);
}

Answered By – Rémi Rousselet

Answer Checked By – Katrina (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published.