使用被处置的观察者不会重新订阅源

时间:2017-10-04 22:12:20

标签: java android rx-android rx-java2

我试图通过仅创建DisposableSingleObserver/DisposableObserver的单个实例并通过流上的subscribeWith()方法将它们传递给它来尝试为单个和可观察流重用Observer,如下所示:

public class SomeClass {
    private DisposableSingleObserver<Object> observer;

    public SomeClass() {
        observer = new DisposableSingleObserver<Object>() {
            @Override
            public void onSuccess(Object object) {
                ...
            }

            @Override
            public void onError(Throwable throwable) {
                ...
            }
        };
    }

    public void doSomeStuff() {
        singleStream.subscribeOn(...)
            .observeOn(...)
            .subscribeWith(observer);
    }
}

当我尝试使用消息多次订阅单个观察者实例时,上面的代码导致ProtocolViolationException

  

io.reactivex.exceptions.ProtocolViolationException:不允许多次订阅(n)com.package.name.SomeClass $ 1。请创建一个com.package.name.SomeClass $ 1的新实例,并将其订阅到目标源。

所以我修改了代码,如下所示:

public class SomeClass {
    ...

    public void doSomeStuff() {
        if (observer != null) {
            observer.dispose();
        }

        singleStream.subscribeOn(...)
            .observerOn(...)
            .subscribeWith(observer);
    }
}

当我执行上面的代码时,ProtocolViolationException不再被抛出,我能够成功地从单个流中获取事件。但是当我尝试几次调用doSomeStuff()方法时,它在第一次调用时成功完成,但在第二次调用时没有发出任何事件。我能够确认订阅发生在doOnSubscribe()两次,但单个流的代码发出事件从未在第二次调用时执行。所以我有三个问题:

  1. 为什么ProtocolViolationException首先被抛出?
  2. 为什么我能够在第一次订阅时获得该活动,但在第二次订阅时却没有,即使我们在这两种情况下订阅了该来源?
  3. 如何只使用一个实例重用观察者?

1 个答案:

答案 0 :(得分:4)

1)您不能重复使用DisposableSingleObserver及其表兄弟,因为它们是有状态的,只能使用一次。这是由于Single强制执行的协议:恰好一个onSubscribe后跟最多一个onSuccessonError。第二个订阅违反了此协议。

2)处置DisposableSingleObserver会使其处于处置状态,任何后续的订阅尝试都将被视为立即处置。

3)你不应该。为什么要多次订阅?为什么每次都不能使用新的DisposableSingleObserver。您应该重新考虑数据流。