java - java.lang.IllegalStateException:应在主线程上调用,但为 RxCachedThreadScheduler-1
问题描述
我是新来的。我正在尝试将 RxJava 库用于 Android,但出现错误。逻辑是处理按钮上的点击事件,然后将其映射到从 中获取值EditText
,然后通过网络flatmap
将Single<String>
其解析为值。我正在尝试flatmap
使用 IO 线程运行Schedulers.io()
,但出现错误:
E/MainActivity: Login error
java.lang.IllegalStateException: Expected to be called on the main thread but was RxCachedThreadScheduler-1
at com.jakewharton.rxbinding3.internal.Preconditions.checkMainThread(mainThread.kt:28)
at com.jakewharton.rxbinding3.view.ViewClickObservable.subscribeActual(ViewClickObservable.kt:35)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at io.reactivex.internal.operators.observable.ObservableMap.subscribeActual(ObservableMap.java:32)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at io.reactivex.internal.operators.observable.ObservableFilter.subscribeActual(ObservableFilter.java:30)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at io.reactivex.internal.operators.observable.ObservableDoOnEach.subscribeActual(ObservableDoOnEach.java:42)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at io.reactivex.internal.operators.observable.ObservableMap.subscribeActual(ObservableMap.java:32)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at io.reactivex.internal.operators.observable.ObservableFlatMapSingle.subscribeActual(ObservableFlatMapSingle.java:48)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at io.reactivex.internal.operators.observable.ObservableObserveOn.subscribeActual(ObservableObserveOn.java:45)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:578)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
编码:
RxView.clicks(this.btnNext)
.map(none -> this.editTextKey.getText().toString())
.filter(x -> !x.isEmpty())
.flatMapSingle(key -> new Api(key).id())
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(this::showId, err -> {
Log.e(this.getClass().getSimpleName(), "Login error", err);
})
Api 类有这个方法:
class Api {
private final String apiKey;
public Api(final String apiKey) {
this.apiKey = apiKey;
}
Single<String> id() {
// some code to fetch user id by key from remote server
}
}
有人可以帮我解决这个问题吗?我需要在后台线程上运行网络调用,但在主线程上接收结果。
解决方案
您正在使用.subscribeOn(Schedulers.io())
事件RxView.clicks(this.btnNext)
源。这意味着RxView
将订阅 IO 线程,但这是不允许的。您应该为您的Single<String>
源配置调度程序flatMapSingle(key -> new Api(key).id().subscribeOn(Schedulers.io()))
。所以完整的代码应该是:
RxView.clicks(this.btnNext)
.map(none -> this.editTextKey.getText().toString())
.filter(x -> !x.isEmpty())
.flatMapSingle(key -> new Api(key).id().subscribeOn(Schedulers.io()))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::showId, err -> {
Log.e(this.getClass().getSimpleName(), "Login error", err);
})
现在网络操作将在 IO 线程上执行,在主线程上查看订阅。
推荐阅读
- c++ - 为 C++ 编程和开发配置 VS 代码
- hive - 列“ex:x 属于字符串类型”的 Parquet 模式不兼容 列类型:STRING、Parquet 模式
- python - 如何将列表列表转换为网格格式的单个字符串?
- python - 找到最大加权子集,使得子集中的任何两个元素总和不等于 k
- azure - 是否可以在工作区上过滤 OMS 仪表板?
- windows - 无法更改服务启动模式
- java - “dev”配置覆盖 Quarkus 中的“test”配置
- ios - Delphi iOs如何检测挂机
- npm - 如何使用 webpack 配置复制 npm 依赖项
- azure - 在 Azure 上的资源组之间移动后删除 microsoft.web/certificates