何时取消订阅订阅

时间:2016-03-02 19:55:46

标签: android rx-java reactive-programming rx-android

我有一个关于如何取消订阅可观察量的问题。我有两个代码,我不确定哪一个更好。

实施例1 - >流完成后取消订阅订阅者:

Subscriber<String> subscriber = new Subscriber<String>() {
        @Override
        public void onCompleted() {
            progressdialog.dissmiss();
            unsubscribe();
        }

        @Override
        public void onError(Throwable e) {
            progressdialog.dissmiss();
        }

        @Override
        public void onNext(String s) {
            // do something with data
        }
    }

实施例2 - &gt;一旦活动被销毁,取消订阅订阅:

private void test(){
    Subscriber<String> subscriber = new Subscriber<String>() {
        @Override
        public void onCompleted() {
            progressdialog.dissmiss();
        }

        @Override
        public void onError(Throwable e) {
            progressdialog.dissmiss();
        }

        @Override
        public void onNext(String s) {
            // do something with data
        }
    };

    subscription = BackendRequest.login(loginRequest)
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(subscriber);

    compositeSubscription.add(subscription);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    this.subscription.unsubscribe();
}

我必须提到我的observable只会发出一次,活动不应该等待来自Observable的更多调用。

哪一个更好?

提前致谢

3 个答案:

答案 0 :(得分:28)

无需在onCompleted取消订阅。看看The Observable Contract

  

当Observable向其发出OnError或OnComplete通知时   观察者,这结束了订阅。观察员不需要发布   取消订阅通知以结束订阅   以这种方式观察。

另一方面,您绝对应该取消订阅onDestroy以防止内存泄漏。

答案 1 :(得分:28)

从两个选项中,第二个选项更好。

在您的第一个示例中,您在unsubscribing方法中onComplete()不需要。如果您到达订阅的onComplete(),您就不再有责任取消订阅。

你的第二个例子是正确的。 CompositeSubscription背后的想法是,您可以向其添加多个Subscriptions,然后立即清理(unsubscribe)。换句话说,这只是让您无需保留需要取消订阅的Subscriptions列表。

使用CompositeSubscription的一个棘手的部分是,如果你曾经unsubscribe它,你可以再次使用它。您可以查看compositeSubscription.add()方法的文档以获取详细信息。简而言之 - 它将直接取消订阅您尝试添加的订阅。这是一个刻意的决定(你可以阅读更多关于它的HERE)。

回到您的示例,在Activity的unsubscribe()中调用onDestroy()很好,可以避免内存泄漏。关于您多次拨打test()方法时出现问题的评论 - 我说您的问题出在其他地方。也许你的用例不应该允许多次调用它,也许你应该在使用新收到的数据之前清理旧数据,等等。也许你已经详细解释了你面临的问题,我们可以提供更多帮助。但就CompositeSubscription而言 - 您正在使用它并正确取消订阅!

答案 2 :(得分:5)

我认为这取决于您的需求。如果活动不会等待任何其他调用,我想你可以取消订阅onCompleted()。

我总是取消订阅onDestroy()

@Override
protected void onDestroy() {
    super.onDestroy();

    if (subscription != null) {
        subscription.unsubscribe();
    }
}

编辑:看看http://reactivex.io/RxJava/javadoc/rx/subscriptions/CompositeSubscription.html

private CompositeSubscription mCompositeSubscription = new CompositeSubscription();

private void doSomething() {
    mCompositeSubscription.add(
        AndroidObservable.bindActivity(this, Observable.just("Hello, World!"))
       .subscribe(s -> System.out.println(s)));
}

@Override
protected void onDestroy() {
    super.onDestroy();
    mCompositeSubscription.unsubscribe();
}