Zeyad Gasser
Zeyad Gasser

Reputation: 1546

RxJava Thread switching

RxBottomNavigationView.itemSelections(sections).map(menuItem -> menuItem.getTitle().toString())
            .observeOn(AndroidSchedulers.mainThread()).map(this::insertCategoryHeadersForSection)
            .subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread())
            .compose(bindToLifecycle()).subscribe(itemInfos -> dishRecyclerAdapter.animateTo(itemInfos));

The code above throws this exception:

java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.
at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:111)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'boolean io.reactivex.internal.fuseable.SimpleQueue.isEmpty()' on a null object reference
at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(ObservableObserveOn.java:172)
at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(ObservableObserveOn.java:252)
at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:109)
at android.os.Handler.handleCallback(Handler.java:739) 
at android.os.Handler.dispatchMessage(Handler.java:95) 
at android.os.Looper.loop(Looper.java:148) 
at android.app.ActivityThread.main(ActivityThread.java:5417) 
at java.lang.reflect.Method.invoke(Native Method)

I am trying to get the itemSelections event from a BottomNavigationView, then map the item to its title (on the main thread), then run a long operation on a background thread, then receive the output of that operation on the main thread again. Help please. thanks in advance.

Upvotes: 0

Views: 835

Answers (1)

akarnokd
akarnokd

Reputation: 69997

You've run into a bug in RxBinding2 that is fixed in the repo but not yet released. The reason for it is that by using subscribeOn(Schedulers.computation()) you don't move the computation into the background but make the RxBottomNavigationView.itemSelections(sections) happen on the background thread which is forbidden and crashes your stream (and app).

You should do this instead:

RxBottomNavigationView.itemSelections(sections)
.subscribeOn(AndroidSchedulers.mainThread())      // <------------------------
.map(menuItem -> menuItem.getTitle().toString())  // main thread
.observeOn(Schedulers.computation())              // <------------------------
.map(this::insertCategoryHeadersForSection)       // background
.observeOn(AndroidSchedulers.mainThread())        // <------------------------
.compose(bindToLifecycle())
.subscribe(itemInfos ->                           // main
    dishRecyclerAdapter.animateTo(itemInfos));

Upvotes: 2

Related Questions