timm_oh
timm_oh

Reputation: 417

RxJava 2 causing CalledFromWrongThreadException to be thrown

Currently trying to mock an api call with RxJava 2 (2.0.6) with delay. It throws a CalledFromWrongThreadException in my view layer (Activity).

Here is my Observable in my presenter

   view.refreshLoadStart();
   Observable.just(createTicketArray(10))
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .delay(5, TimeUnit.SECONDS)
            .subscribe(new Observer<ArrayList<Ticket>>() {
                @Override
                public void onSubscribe(Disposable d) {

                }

                @Override
                public void onNext(ArrayList<Ticket> tickets) {
                    if (getView() != null){
                        view.showTickets(tickets);
                    }
                }

                @Override
                public void onError(Throwable e) {
                    e.printStackTrace();
                    if (getView() != null){
                        view.refreshLoadComplete();
                    }
                }

                @Override
                public void onComplete() {
                    if (getView() != null){
                        view.refreshLoadComplete();
                    }
                }
            });

Here is my view methods in my activity

    @Override
public void showTickets(final ArrayList<Ticket> tickets) {


//        runOnUiThread(new Runnable() {
//            @Override
//            public void run() {
    if (recyclerView.getAdapter() == null){
        adapter = new TicketAdapter(tickets);
        recyclerView.setAdapter(adapter);
    } else {
        adapter.setTickets(tickets);
        adapter.notifyDataSetChanged();
    }
    recyclerView.setHasFixedSize(true);
//            }
//        });

}

@Override
public void refreshLoadComplete() {
//        runOnUiThread(new Runnable() {
//            @Override
//            public void run() {
    swipeRefreshLayout.setRefreshing(false);
    Toast.makeText(TicketActivity.this, "Completed", Toast.LENGTH_SHORT).show();
//            }
//        });
}

@Override
public void refreshLoadStart() {
//        runOnUiThread(new Runnable() {
//            @Override
//            public void run() {
    swipeRefreshLayout.setRefreshing(true);
//            }
//        });
}

Here is the stacktrace of the exception:

Process: com.timmccarthy.litt, PID: 22060
                                                                  io.reactivex.exceptions.UndeliverableException: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
                                                                      at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:366)
                                                                      at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:62)
                                                                      at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:51)
                                                                      at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                                                                      at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:154)
                                                                      at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269)
                                                                      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
                                                                      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
                                                                      at java.lang.Thread.run(Thread.java:818)
                                                                   Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
                                                                      at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:8128)
                                                                      at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1220)
                                                                      at android.view.View.requestLayout(View.java:20085)
                                                                      at android.view.View.requestLayout(View.java:20085)
                                                                      at android.view.View.requestLayout(View.java:20085)
                                                                      at android.view.View.requestLayout(View.java:20085)
                                                                      at android.view.View.requestLayout(View.java:20085)
                                                                      at android.view.View.requestLayout(View.java:20085)
                                                                      at android.view.View.requestLayout(View.java:20085)
                                                                      at android.view.View.requestLayout(View.java:20085)
                                                                      at android.support.v7.widget.RecyclerView.requestLayout(RecyclerView.java:3576)
                                                                      at android.support.v7.widget.RecyclerView$RecyclerViewDataObserver.onChanged(RecyclerView.java:4620)
                                                                      at android.support.v7.widget.RecyclerView$AdapterDataObservable.notifyChanged(RecyclerView.java:10448)
                                                                      at android.support.v7.widget.RecyclerView$Adapter.notifyDataSetChanged(RecyclerView.java:6105)
                                                                      at com.timmccarthy.litt.ui.ticket.TicketActivity.showTickets(TicketActivity.java:82)
                                                                      at com.timmccarthy.litt.ui.ticket.TicketPresenter$1.onNext(TicketPresenter.java:46)
                                                                      at com.timmccarthy.litt.ui.ticket.TicketPresenter$1.onNext(TicketPresenter.java:37)
                                                                      at io.reactivex.observers.SerializedObserver.onNext(SerializedObserver.java:111)
                                                                      at io.reactivex.internal.operators.observable.ObservableDelay$DelayObserver$1.run(ObservableDelay.java:84)
                                                                      at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:59)
                                                                      at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:51) 
                                                                      at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
                                                                      at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:154) 
                                                                      at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269) 
                                                                      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
                                                                      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
                                                                      at java.lang.Thread.run(Thread.java:818) 

Basically I am asking why is this Exception being thrown since on the Observable I am observing on the main thread and not on another thread?

p.s I did find a fix which is the commented out sections in my code, I just see this as a quick fix and it doesn't really address why I am getting the Exception.

Upvotes: 0

Views: 1575

Answers (2)

timm_oh
timm_oh

Reputation: 417

Figured out where I went wrong.

My 'swipetorefresh' listener was calling a refresh method on my presenter which had a separate observable.

Removed this second observable, all the problems went away.

Upvotes: 0

Remario
Remario

Reputation: 3863

It is rather simply actually ,you are modifying views not in the main thread. try this subscribeOn(Schedulers.newThread()).

does this line gets executed? Toast.makeText(TicketActivity.this, "Completed", Toast.LENGTH_SHORT).show(); the commented out sections wont work because you already on the main thread.

Upvotes: 1

Related Questions