Search code examples
androidrx-javarx-androidsqlbrite

Why is onNext not getting called when using toList?


I'm having an issue with onNext not getting called when using the RxJava toList operator. Everything works exactly as I expect up until the toList gets called. Things I've read here, here and here seem to indicate the issue with onCompleted not being called but I'm still new to RxJava so I'm not sure where I would need to call that in order for this to work.

The most confusing thing is that the architecture I was trying to follow from Google's Android Architecture doesn't seem to call onCompleted and it works just fine.

Subscription subscription = mDataSource
        // Get Observable<List<Location>> from SQLBrite database
        .getLocations()
        // Convert to Location object
        .flatMap(new Func1<List<Location>, Observable<Location>>() {
            @Override
            public Observable<Location> call(List<Location> locations) {
                return Observable.from(locations);
            }
        })
        // Filter here
        .filter(new Func1<Location, Boolean>() {
            @Override
            public Boolean call(Location location) {
                return mPreferences.getUsesCustomLocations() || location.getId().length() <= 2;
            }
        })
        // Convert Location object to String
        .map(new Func1<Location, String>() {
            @Override
            public String call(Location location) {
                return location.getTitle();
            }
        })
        // Convert to Observable<List<String>, however using toList()
        // causes onNext() to never get called
        .toList()
        .subscribeOn(mSchedulerProvider.computation())
        .observeOn(mSchedulerProvider.ui())
        .subscribe(new Observer<List<String>>() {
            @Override
            public void onCompleted() {
            }

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

            @Override
            public void onNext(List<String> locations) {
                processLocations(locations);
            }
        });
    mSubscriptions.add(subscription);

Solution

  • After calling toList() you will only get a single onNext() and that is when the source observable calls onComplete().

    The reason for the behaviour that you are seeing is SQLBrite, which will send you the data every time it is changed. This means it is an unending stream so it ends up never calling onComplete().