RxJava - 根据另一个流取消订阅(重新)订阅

时间:2017-12-25 08:18:02

标签: android rx-java

我有这种情况: 一个很快产生物品的流 在UI线程上做了大量工作的订阅者。

当遇到某种情况时,我想取消订阅,以免发生额外的工作。

我还想在重新订阅的情况下做一些额外的工作。

实施例: 网络事件产生对项目的更新,模型监听它并更新项目并使用更新的项目公开新的observable。 屏幕订阅模型的流并相应地更新GUI。 一个新的屏幕打开,所以我们不再需要在前一个屏幕上更新它的GUI了 - >取消订阅(当模型仍在更新时) 新屏幕关闭,使前一个屏幕再次可见,因此需要重新订阅,因为它没有听过一段时间需要刷新它的视图。

我有一些解决方案,但我觉得可能有更好的解决方案:

我可以使用过滤器来检查条件。并且只是过滤那些项目,但我更喜欢完全取消订阅,因为它会更有效率。

isScreenVisibleObs().subscribe(isVisible -> {
if (isVisible){
    subscription = getItemsUpdateObs().subscribe(...) 
} else { 
    if ( subscription != null) subscription.unsubscribe() 
}});

我可以用来订阅和监听条件事件。然后根据该事件订阅/取消订阅每次都有一个全新的订阅 - 这是一个程序解决方案而不是功能解决方案。 我想过使用窗口操作符并将其展平,但我不确定这是一个简单的解决方案。

getItemsUpdateObs().compose(listenWhen(isScreenVisibleObs()).subscribe(...)

有什么想法吗?

我想这样做:

json.dumps (data)

哪里听,这里的问题是什么......

3 个答案:

答案 0 :(得分:1)

保存Observable.subscribe()方法的返回类型。在上一个屏幕的onActivityResult中再次重新发起请求

 Subscription subscription =  Observable.subscribe(new Subscriber<Type>() {
        @Override
        public void onCompleted() {
        }

        @Override
        public void onError(Throwable e) {
        }

        @Override
        public void onNext(String responseString) {
        }
    });

每当您提出下一个请求时,只需检查之前的呼叫状态(已完成/正在运行)         如下。如果没有完成取消上一个电话,并按如下方式提出新请求。

 if(subscription!=null && !subscription.isUnsubscribed()){
      //Cancel(unSubscribe) the request if running(not completed)
      subscription.unsubscribe();
      //START A NEW REQUEST HERE
 }else{
      //already completed so START A NEW REQUEST
 }

答案 1 :(得分:1)

RxJava中有一个名为switchMap()的非常有用的运算符。它将根据可观察的内容切换订阅。

首先根据您的屏幕是否处于活动状态来设置您的observable:

Observable<Boolean> isActive;

然后,根据可观察的内容进行切换:

isActive
  .switchMap( active -> active ? getItemsUpdateObs() : Observable.never() )
  .subscribe( ... );

这只会在屏幕处于活动状态时订阅项目更新。每个屏幕需要一个可观察的,但它们很便宜。这样,可观察链保持其自身状态,并为您处理订阅和重新订阅的正确管理和时间。

答案 2 :(得分:0)

我甚至不关心前一个下属是否完成。在您要为新请求创建新订户的下一个窗口中,只需取消订阅订阅,所有订阅者将自动取消订阅。

然后创建一个新订阅者并再次订阅该订阅。

/**
 * You can in any moment unsubscribe all subscriber of a subscription and create a new one again.
 * @throws InterruptedException
 */
@Test
public void subscribeAndUnsubscribe() throws InterruptedException {
    Integer[] numbers = {0, 1, 2, 4, 5, 6};
    Observable<Integer> observable = Observable.from(numbers);
    Subscription subscription = observable.subscribeOn(Schedulers.newThread()).subscribe(createSubscriber());
    Thread.sleep(2000);
    subscription.unsubscribe();
    subscription = observable.subscribeOn(Schedulers.newThread()).subscribe(createSubscriber());
    Thread.sleep(10000);
    System.out.println(subscription.isUnsubscribed());
}

private ActionSubscriber createSubscriber() {
    return new ActionSubscriber(number -> {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            System.out.println("preparing to unsubscribe");
        }
        System.out.println("Subscriber number:" + number);
    },
            System.out::println,
            () -> System.out.println("Subscriber End of pipeline"));
}

您可以在此处查看更多示例https://github.com/politrons/reactive/blob/master/src/test/java/rx/observables/creating/ObservableSubscription.java