java.lang.IllegalStateException: ожидалось, что он будет вызван в основном потоке, но был RxCachedThreadScheduler-1 - PullRequest
1 голос
/ 21 сентября 2019

Я новичок здесь.Я пытаюсь использовать библиотеку RxJava для Android, но получаю ошибку.Логика заключается в том, чтобы обрабатывать события нажатия на кнопку, затем сопоставлять ее, чтобы получить значение от EditText, а затем flatmap это до Single<String>, что разрешает значение через сеть.Я пытаюсь запустить flatmap в потоке ввода-вывода, используя 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
  }
}

Может кто-нибудь помочь мне решить эту проблему?Мне нужно выполнить сетевые вызовы в фоновом потоке, но получить результат в основном потоке.

1 Ответ

2 голосов
/ 21 сентября 2019

Вы используете .subscribeOn(Schedulers.io()) для RxView.clicks(this.btnNext) источника событий.Это означает, что RxView будет подписываться на поток ввода-вывода, но это не разрешено.Вы должны настроить планировщик для вашего 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);
  })

Теперь сетевая операция будет выполняться в потоке ввода-вывода, просмотр подписки в основном потоке.

...