如何在运行时“合并”可观察量?

时间:2015-09-16 21:51:48

标签: rx-java

我的用例是视图组中的单击侦听器:

  • 每个View都会发布一个冷Observable<Click> API。

  • 视图组管理一组视图,并提供一个Observable<ViewClick> API,可以从子视图中发出点击。

我希望在添加到复合observable时订阅每个子视图,但前提是复合具有订阅。如果不是,则只有在订阅了合成时才应订阅该子项。

到目前为止,我的解决方案是:

PublishSubject<ViewClick> composite;
Map<View, Subscription> subscriptions;

void addSource(View view, Observable<Click> clicks) {
    Subscription s = clicks.map(click -> new ViewClick(view, click)
     .subscribe(composite::onNext);
    subscriptions.put(view, s);
}

void removeSource(View v) {
    Subscription s = subscriptions.get(v);  
    s.unsubscribe;
    subscriptions.remove(v);  
}

Observable<ViewClick> compositeClicks() {
    return composite;
}

但是,这意味着clicks可观察对象不再冷,因为无论是否有任何订阅compositeClicks,他们都会订阅。

有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

你需要一个特殊的“温暖”主题,例如BufferUntilSubscriber,它保留在源Observables上,直到一个消费者订阅它为止。不幸的是,该类不是官方API的一部分,但是,出于同样的目的,2.0将有一个官方UnicastSubject

UnicastSubject<Observable<Integer>> inputs = UnicastSubject.create();

Observable<String> p = inputs
        .flatMap(v -> v.map(u -> u.toString()))
        .publish()
        .autoConnect()
        ;

inputs.onNext(Observable.just(1)
    .doOnSubscribe(s -> System.out.println("Subscribed to 1")));
inputs.onNext(Observable.just(2)
    .doOnSubscribe(s -> System.out.println("Subscribed to 2")));
inputs.onNext(Observable.just(3)
    .doOnSubscribe(s -> System.out.println("Subscribed to 3")));

System.out.println("Subscribing to p");

p.subscribe(System.out::println);

答案 1 :(得分:0)

你的困难来自于addSource / removeSource不是被动的,并且如果你把它们变成Rx流就会逃脱。

有几种方法可以做到:

  • IObservable<IObservable<View>>内部可观察者在激活/添加时会有一个onNext,并且会在删除后onComplete
  • IObservable<View> x2(一个用于添加,一个用于删除)
  • IObservable<ViewActivationEvent>(添加/删除种类+视图实例的元组)

(假设您的点击流可以从视图中提取,否则您需要提供一个元组视图+ clickStream来代替视图,用于激活部分)

以下是使用上述#2实现您的流的方式,但所有方法都可以使用:

Subject<View> add,remove;

clicks = add.flatMap(view -> getClickObservable(view).takeUntil(remove.where(v => v == view)))