alihabbash95
alihabbash95

Reputation: 125

Only the original thread that created a view hierarchy can touch its views using Rxjava

My problem is a got an error when I click quickly multiple time on bottomNavigationView I got this error:

Only the original thread that created a view hierarchy can touch its views.

I handle bottomNavigationView clicks by using Rxbinding. model.getNews() retrun a Single<> observable.

My code for handling bottomNavigationView clicks is:

    private Disposable loadNews(int categoryNumber) {

    return model.getNews(1, categoryNumber, OrderBy.DESC)
            .observeOn(AndroidSchedulers.mainThread())
            .doFinally(() -> view.showLoading(false))
            .doOnSubscribe(__ -> view.showLoading(true) )
            .subscribeOn(Schedulers.io())
            .retry()
            .map(NewsResponse::newsDetails)
            .subscribe(newsDetails -> view.setUpRecyclerView(newsDetails),
                    throwable -> ToastUtils.showShort("Error " + throwable.getMessage()
                            + "Caused by " + throwable.getCause()));

}

Upvotes: 3

Views: 572

Answers (2)

Peddro
Peddro

Reputation: 1155

I think you need to add another observeOn(AndroidSchedulers.mainThread()) lower in the stream, like so:

private Disposable loadNews(int categoryNumber) {

    return model.getNews(1, categoryNumber, OrderBy.DESC)
            .observeOn(AndroidSchedulers.mainThread())
            .doFinally(() -> view.showLoading(false))
            .doOnSubscribe(__ -> view.showLoading(true) )
            .subscribeOn(Schedulers.io())
            .retry()
            .map(NewsResponse::newsDetails)
            .observeOn(AndroidSchedulers.mainThread()) <-- HERE!
            .subscribe(newsDetails -> view.setUpRecyclerView(newsDetails),
                    throwable -> ToastUtils.showShort("Error " + throwable.getMessage()
                            + "Caused by " + throwable.getCause()));

}

Upvotes: 4

technoplato
technoplato

Reputation: 3431

It may not be a direct fix for why your code attempts to access the views from a non-main thread, but I believe a simple band-aid fix would be simply debouncing clicks on the bottomNavigationView.

Code for that would look something like this (from memory, so please let me know if this doesn't work):

RxBinding.clicks(bottomNavigationView)
    .debounce(
        300 /* Time to debounce according to TimeUnit specified below */,
        TimeUnit.MILLIS
    )
    // .... continue with the rest of your Rx chain

Upvotes: 0

Related Questions