Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJava doOnError vs onError

I am try to use the following code

initLocalSettingsIfNeed()
                            .andThen(initGlobalSettingsIfNeed(configuration))
                            .doOnComplete(callback::onSuccess)
                            .doOnError(throwable -> callback.onError(throwable.getLocalizedMessage()))
                            .subscribe();

But I have exception

The exception was not handled due to missing onError handler in the subscribe() method call.

I guess I am not using this methods correctly, I thought can replace doOnComplete doOnError with observer inside subscribe() method, I am wrong?

like image 760
Pavel Poley Avatar asked Apr 16 '19 12:04

Pavel Poley


People also ask

What is doOnError?

doOnError. doOnError is used to add side effect behaviour triggered just before the error is sent downstream, as you can see below this is different from onErrorResume as the error will be propagated to subsequent operators (you can for example use it for instrumentation purposes).

Is onComplete called after OnError?

An Observable may make zero or more OnNext notifications, each representing a single emitted item, and it may then follow those emission notifications by either an OnCompleted or an OnError notification, but not both.

What is onErrorResumeNext RxJava?

Similar to onErrorReturn() and onErrorReturnItem() , onErrorResumeNext() is very similar. The only difference is that it accepts another Observable as a parameter to emit potentially multiple values, not a single value, in the event of an exception.


2 Answers

Regarding your original question, you have to know that doOnError is not a replacement of onError. You have a good and short explanation about it in this blog:

Actually there’s one key difference between them. doOnError() basically only triggers its callback, then passes down the encountered errors to the down stream. So if the whole stream is subscribed without the onError callback in subscribe(), your app will crash by OnErrorNotImplementedException.

The onError callback in subscribe() in the other hand does consume the errors. That means, it will catch the errors, and let you handle them without re-throwing the errors by itself.

About the warning you mention in one comment:

This approach is working, but i have warning 'the result of subscribe not used', as i know this need to be disposed automatically when onError or onComplete is called, is there way to avoid this warning? – Pavel Poley

A good approach is that your methods inside your Repository return a Observable, and then you can subscribe to them in your ViewModel. Then, in every ViewModel class you can have a member variable with a CompositeDisposable where you can add the disposable of each subscription to the Observables returned by your repository. Finally, you should override the onCleared method to dispose all the disposables stored in the CompositeDisposable.

public class MyViewModel extends ViewModel {

    private MyRepository myRepository;
    private final CompositeDisposable disposables;

    @Inject
    public MyViewModel(MyRepository myRepository) {
        ...
        this.myRepository = myRepository;
        disposables = new CompositeDisposable();
        ...
    }

    public void callObservableInRepository() {
         disposables.add(myRepository.myObservable()
                              .subscribe(onSuccess -> {...} , onError -> {...}));
    }

    @Override
    protected void onCleared() {
        disposables.clear();
    }

}
like image 58
dglozano Avatar answered Oct 20 '22 10:10

dglozano


try this

initLocalSettingsIfNeed()
    .andThen(initGlobalSettingsIfNeed(configuration))
    .subscribe({completed->
        callback.onSuccess()
    },{throwable->
        callback.onError(throwable.getLocalizedMessage())
    })
like image 23
Antonis Radz Avatar answered Oct 20 '22 08:10

Antonis Radz