1
votes

My Question is probably more of the conceptual nature.
I get that by the Observable contract my Observable will not emit any more items after onComplete or onError is called.
But I'm using the RxBindings for Android and therefore it's not "my Observable" but the click on a Button that emits items.

fun observeForgotPasswordButton(): Disposable {
    return view.observeForgotPasswordButton()
            .flatMap {
                authService.forgotPassword(email).toObservable<Any>()
            }
            .subscribe({
                // on next
                Timber.d("fun: onNext:")
            }, { error ->
                // on error
                Timber.e(error, "fun: onError")
            }, {
                // onComplete
                Timber.d("fun: onComplete")
            })
}

observeForgotPasswordButton() returns an Observable

fun observeForgotPasswordButton(): Observable<Any> = RxView.clicks(b_forgot_password)

The problem is that authService.forgotPassword(email) is a Completable and it will call either onComplete or onError both of which lead to the fact that I cannot reuse the button anymore since the subscription ended.
Is there a way to circumvent this behavior? Because in an error occurs I would like to be able to retry.
Also I would like it to be possible to send more then one password forgotten emails.

1
The only way for the above to get unsubscribed prematurely is for an error to happen. I think onComplete won't be called if forgotPassword is always successful. Check rxJava error handling operators. Also you can use flatMapCompletablemasp
I did some more digging and found a pretty solid explanation of error handling in rx. As the blog post describes it, I made the rookie mistake of throwing an exception in the authService instead of calling onNext with an error state. This is the rx-way...grAPPfruit
@grAPPfruit using onError instead of modeling an Error state isn't a real rookie mistake. Even Square's Retrofit did that once.Phoenix Wang
@PhoenixWang made my day ;)grAPPfruit

1 Answers

2
votes

You can use the retry() and repeat() operators to automatically resubscribe to the original Observable (or Completable).

fun observeForgotPasswordButton(): Disposable {
    return view.observeForgotPasswordButton()
            .flatMap {
                authService.forgotPassword(email).toObservable<Any>()
            }
            .repeat() // automatically resubscribe on completion
            .retry()  // automatically resubscribe on error
            .subscribe({
                // on next
                Timber.d("fun: onNext:")
            }, { error ->
                // on error
                Timber.e(error, "fun: onError")
            }, {
                // onComplete
                Timber.d("fun: onComplete")
            })
}