3

When I turned off Internet and swipe to refresh on first time, everything works ok (refreshing disabling, and showing NetworkErrorView), but when I swipe to refresh on second time, refreshing status freezing, and as I understand in SingleObserver not calling neither onSuccess (because internet off, okay), nor onError, which should calling because Internet is off, as a result doAfterTerminate also not calling.

By the way,

dataManager.getCitiesFromDb() return Observable(City) and dataManager.getCityConditionsResponse() return Single(List(City))

MainActivity (onCreate)

presenter.setRefreshObservable(RxSwipeRefreshLayout.refreshes(swipeRefreshLayout));

Presenter

@Override
public void setRefreshObservable(Observable<Object> observable) {
    observable
            .flatMapSingle(l -> getCitiesListObservable()
                    .flatMap(list -> Single.fromObservable(Observable.fromIterable(list)))
                    .map(city -> city))
            .toList()
            .subscribe(new SingleObserver<List<City>>() {
                @Override
                public void onSubscribe(Disposable d) {
                    disposables.add(d);
                }

                @Override
                public void onSuccess(List<City> list) {
                    view.showCitiesList(list);
                }

                @Override
                public void onError(Throwable e) {
                    view.showNetworkErrorView();
                }
            });
}

private Single<List<City>> getCitiesListObservable() {
    return dataManager.getCitiesFromDb()
            .flatMapSingle(city ->
                    dataManager.getCityConditionsResponse(city.getQuery())
                            .map(response -> {
                                city.setTemp(response.getTemp());
                                city.setIcon(response.getIcon());
                                return city;
                            })
            )
            .toList()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .doAfterTerminate(() -> view.hideRefreshingStatus());
}
sharonooo
  • 684
  • 3
  • 8
  • 25
Mike
  • 79
  • 2
  • 9

1 Answers1

3

If an observable emits an error in RxJava, it is terminated so you can not re-use that stream anymore.
Here in your case, when your network request (probably dataManager.getCityConditionsResponse method) gives you error because of internet, your stream is broken.
To handle this you have to add RxJava's onErrorReturn to your network request to not emit error. As, it won't emit error to down stream, your stream will not be broken. Eventually, it can continue emitting more item.

bkrcinar
  • 345
  • 1
  • 7
  • So using this method I can create StateUtils class with Boolean variable. And in onErrorReturn I will initialize with variable, and instead of list return I will return null. And then all error handling will be only in onSuccess, because onError won’t be invoked due to onErrorReturn method. And for example if Boolean true then showNetworkError, and if false showServerError – Mike Oct 17 '18 at 09:14
  • How to take care of state issue is completely another topic. My suggestion would be create a model consisting success as boolean, data as your data and error as throwable(or error model to check if it is network or server error) and return that model. In onSuccess you have to handle success case and error case checking success and error fields inside your model. – bkrcinar Oct 17 '18 at 09:22
  • I understand u, but plz answer on last question where better call onErrotReturn in network call, or after toList() (post network call), or it doesnt’t matter – Mike Oct 17 '18 at 09:26
  • Wait, i deleted my last comment cause i misunderstood it. You have to put it after network call, thats the one giving you error. – bkrcinar Oct 17 '18 at 09:36
  • So, in my code after map (it’s looping, because cities from DB is Iterable observable) or after toList()? I think after toList(), this can prevent multiple initializing values in StateModel class, if error happened – Mike Oct 17 '18 at 09:48
  • Actually it depends how you want to handle. I was thinking that you are making network request for every city to get conditions. Lets say you have 50 city and already made 50 call but one out of 50 failed. If you put it after `toList()`, you have to redo all 50 request again. However, if you redesign a bit your models and put `onErrorReturn` after mapping, you can show just this one error and preferably later make one request. If you say, even one fail i will show a big error to user and redo all requests again, put it after `toList`. – bkrcinar Oct 17 '18 at 10:02
  • You’re right, I have network call in loop. I want to finish looping (getting conditions for cities) if error happened, and init variables of StateModel class, for further error handling (show network or server error views) – Mike Oct 17 '18 at 10:21