2015-09-16 29 views
3

我的使用情况,这是单击视图组听众:如何在运行时“合并”observables?

  • 每个View发布感冒Observable<Click> API。

  • 视图组管理视图集合,并提供一个Observable<ViewClick> API,它发出来自子视图的点击。

我希望每个子视图在添加到组合观察值时被订阅,但仅当组合具有订阅时才被订阅。如果不是,则只有在组合订阅时才应该订阅该孩子。

到目前为止,我的解决办法是:

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认购。

有没有更好的方法?

回答

0

你的困难来自于一个事实,即ADDSOURCE/removeSource都没有反应,和如果您将它们制作为Rx流,它们将会消失。

几种方法做到这一点:

  • IObservable<IObservable<View>>其中内观测将在激活时有一个单一的onNext /添加,并且将onComplete在除去。
  • IObservable<View> X2(一个加,一个用于去除)
  • IObservable<ViewActivationEvent>(元组添加/删除实物+查看实例)

(假设你的点击流可以从视图中提取,否则你需要提供一个元组视图+点击流到位的看法,激活部分)

这里是如何执行你的流将看起来像上面的#2,但所有的方法可以工作:

Subject<View> add,remove; 

clicks = add.flatMap(view -> getClickObservable(view).takeUntil(remove.where(v => v == view))) 
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);