创建一个可观察的对象,该对象在订阅时生成一个Single,但会停止并重用特定的值

时间:2018-11-16 20:42:13

标签: retrofit2 rx-java2

我正在使用Retrofit进行API调用,该API返回一个Single,并且我使用onErrorReturn将任何异常转换为默认对象。我希望消费者看到当前值,但是如果当前值是默认对象,我想尝试重新查询API并另外发送结果。使事情复杂化的是,我可能有多个订阅者。

因此,我知道Retrofit Single必须转换为适当的Observable流,而不仅仅是像普通{那样的onNext / onComplete {1}}可以,但是我不知道如何仅使用Single.toObservable中的Single来重新查询API并将值推回给以前的订阅者。

现在,我知道了

Retrofit

但是我知道调用fun request(): Observable<Foo> { if (behaviorSubject.value == defaultObject) { API .request() .onErrorReturn(defaultObject) .subscribe(behaviorSubject) } return behaviorSubject } 违反了Rx链接,所以我试图找出解决方法。

1 个答案:

答案 0 :(得分:0)

感谢您提出有趣的情况。我认为这是一个可以满足您要求的解决方案。它比您的解决方案更长,但在涉及多个订阅时应该是安全的。

// subscribe to this observable with one or more subscribers
val requestObservable = replayAndRetry(API.request(), defaultObject)

private fun <T> replayAndRetry(request: Single<T>, defaultValue: T): Observable<T> {
    val responses = BehaviorSubject.create<T>()

    val initialRequest = request
            .onErrorReturnItem(defaultValue)
            .doOnSuccess(responses::onNext)
            .ignoreElement()
            .cache() // run the initial request at most once

    val retryWhenNecessary = Maybe
            .fromCallable { if (responses.value == defaultValue) true else null }
            .flatMapCompletable { request
                    .doOnSuccess(responses::onNext)
                    .ignoreElement()
                    .onErrorComplete() // subject already has the default value
            }
            .toObservable<T>().share() // avoid multiple simultaneous retries

    return responses // source for all responses
            .mergeWith(initialRequest) // will run once and then complete
            .mergeWith(retryWhenNecessary) // will check for default item on every subscription
                                           // will not run simultaneous retries
}