RxJava 2 导致抛出 CalledFromWrongThreadException
RxJava 2 causing CalledFromWrongThreadException to be thrown
目前正在尝试使用 RxJava 2 (2.0.6) 延迟模拟 api 调用。
它在我的视图层 (Activity) 中抛出 CalledFromWrongThreadException。
这是我的 Presenter 中的 Observable
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();
}
}
});
这是我在 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);
// }
// });
}
这是异常的堆栈跟踪:
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.access1(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.onNext(TicketPresenter.java:46)
at com.timmccarthy.litt.ui.ticket.TicketPresenter.onNext(TicketPresenter.java:37)
at io.reactivex.observers.SerializedObserver.onNext(SerializedObserver.java:111)
at io.reactivex.internal.operators.observable.ObservableDelay$DelayObserver.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.access1(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)
基本上我问的是为什么抛出这个异常,因为我在主线程而不是另一个线程上观察 Observable?
p.s 我确实找到了一个修复程序,它是我代码中注释掉的部分,我只是将其视为一个快速修复程序,它并没有真正解决我出现异常的原因。
其实很简单,你修改的视图不是在主线程中。试试这个 subscribeOn(Schedulers.newThread())
.
这一行是否被执行? Toast.makeText(TicketActivity.this, "Completed", Toast.LENGTH_SHORT).show();
注释掉的部分将不起作用,因为您已经在主线程上了。
找出我哪里出错了。
我的 'swipetorefresh' 侦听器在我的演示器上调用刷新方法,它有一个单独的可观察对象。
删除了第二个 observable,所有问题都消失了。
目前正在尝试使用 RxJava 2 (2.0.6) 延迟模拟 api 调用。 它在我的视图层 (Activity) 中抛出 CalledFromWrongThreadException。
这是我的 Presenter 中的 Observable
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();
}
}
});
这是我在 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);
// }
// });
}
这是异常的堆栈跟踪:
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.access1(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.onNext(TicketPresenter.java:46)
at com.timmccarthy.litt.ui.ticket.TicketPresenter.onNext(TicketPresenter.java:37)
at io.reactivex.observers.SerializedObserver.onNext(SerializedObserver.java:111)
at io.reactivex.internal.operators.observable.ObservableDelay$DelayObserver.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.access1(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)
基本上我问的是为什么抛出这个异常,因为我在主线程而不是另一个线程上观察 Observable?
p.s 我确实找到了一个修复程序,它是我代码中注释掉的部分,我只是将其视为一个快速修复程序,它并没有真正解决我出现异常的原因。
其实很简单,你修改的视图不是在主线程中。试试这个 subscribeOn(Schedulers.newThread())
.
这一行是否被执行? Toast.makeText(TicketActivity.this, "Completed", Toast.LENGTH_SHORT).show();
注释掉的部分将不起作用,因为您已经在主线程上了。
找出我哪里出错了。
我的 'swipetorefresh' 侦听器在我的演示器上调用刷新方法,它有一个单独的可观察对象。
删除了第二个 observable,所有问题都消失了。