RxDart, отображающий каждый элемент списка в другой объект, поступающий из бесконечного потока - PullRequest
0 голосов
/ 26 ноября 2018

Я пытался найти хороший способ сделать это, но мне не повезло.

Вот упрощенная версия проблемы:

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");
  });
}

При запуске этого,ничего не напечатано.Это происходит потому, что субъект никогда не завершает работу и, следовательно, toList() никогда не завершает построение списка.

Замена субъекта, например, Observable.just(index + 2), работает, потому что Observable завершается и toList() может собратьих.

Но предполагаемое поведение состоит в том, что пример должен генерировать новый список строк при каждом изменении темы.

Любая помощь будет принята,

Спасибо!

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

Редактировать : вскоре после публикации я понял, что это полностью зависит от того, как данные предоставляются:

Если у вас есть метод, который имеет подпись, такую ​​как Observable<String> getStringForInt(int number), и у вас естьчтобы позвонить по каждому пункту в списке, мое решение для вас. Примечание , если описанный выше метод всегда подписывается на один и тот же поток, изменение этого потока приведет к нескольким выбросам (так как combLatest обновляет каждый элемент).

Однако, если у вас есть доступ ко всем даннымКонтейнер (например, Карта

Оригинальный ответ

Хорошо, оказывается, достичь этого с помощью rxDart было не совсем возможно.

Конструктор combineLatest поддерживает только до 9 потоков.

Но с тех пор было реализовано комбинирование последнего с n-потоками, и решение этой проблемы могло бы выглядеть примерно так:

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

void main() async {

  Observable.fromIterable([1, 2, 3, 4, 5])
      .toList().asObservable()
      .flatMap((numbers) =>
      Observable.combineLatest<String, List<String>>(numbers.map((index) => subject2[index]), (strings) => strings))
      .listen((data) {
    print("List of data incoming $data");
  });

  await Future.delayed(Duration(seconds: 2));
  subject2[1].add("I'm 42 now");
}

Это напечатает:

List of data incoming [Subject 1, Subject 2, Subject 3, Subject 4, Subject 5]
List of data incoming [I'm 42 now, Subject 2, Subject 3, Subject 4, Subject 5]
0 голосов
/ 26 ноября 2018

Вы, вероятно, хотите использовать ОбъединитьПоследний вместо

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]);
}
...