Rx Java Наблюдать, похоже, не работает правильно - PullRequest
0 голосов
/ 09 мая 2020

Я столкнулся с этой ошибкой от Rx Java

Android «Только исходный поток, создавший иерархию представлений, может касаться его представлений».

код, который я использовал

Log.d(TAG, "stratObserving:qw ${Thread.currentThread()}")
(application as? App)?.relayPages
                ?.doAfterNext{
                    hideLoading()
                }
                ?.observeOn(AndroidSchedulers.mainThread())
                ?.subscribe({
                   "data found ${it.size}".log()
                    pageAdapter.setPageList(it)
                    rvAyahsPages.scrollToPosition(pos)
                    "data pageAdapter ${pageAdapter.itemCount} , ${Thread.currentThread()}".log()
                    foundState()
                }, {
                    "error ${it.message}".log()
                })
                ?.addTo(model.bg)
 private fun foundState() {
        spShowAyahs?.visibility = View.GONE
        tvNoQuranData?.visibility = View.GONE
        rvAyahsPages?.visibility = View.VISIBLE
        "found $rvAyahsPages $spShowAyahs".log()
    }

, однако

Log.d(TAG, "stratObserving:qw ${Thread.currentThread()}") печать Thread [main,5,main]

и

Log.d(TAG, "stratObserving:qw ${Thread.currentThread()}") print Thread [main,5,main]

[Примечание]

Этот вопрос отличается от «Android« Только исходный поток, создавший иерархию представлений, может касаться его представлений ». "отвечает, что решение заключалось в запуске на MainThread, но здесь оно фактически выполнялось на MainThread

[Edit] проблема заключалась в упорядочивании операторов, поэтому замените doAfterNext на Наблюдать .

1 Ответ

0 голосов
/ 10 мая 2020

Как уже упоминали @fraggjkee и @EpicPandaForce, проблема здесь:

(application as? App)?.relayPages
                ?.doAfterNext{
                    hideLoading()
                }

В чем проблема: Android «Только исходный поток, создавший иерархию представлений, может коснуться его просмотров

Эта проблема возникает, когда кто-то пытается обновить состояние пользовательского интерфейса из потока, отличного от пользовательского интерфейса. UI-eventl oop является однопоточным. Поэтому запрещено, чтобы другие потоки обновляли UI-состояние (например, свойства просмотра и др. c.)

Почему «ObserveOn» не работает?

(application as? App)?.relayPages
                ?.doAfterNext{
                    hideLoading()
                }
                ?.observeOn(AndroidSchedulers.mainThread())

ObserveOn переключает поток с одного оператора на другой в наблюдаемом. Когда relayPages выдает значение, оно будет проходить через doAfterNext в любом заданном потоке, скорее всего, в потоке-подписчике. После прохождения doAfterNext exmit будет go через ObserveOn-operator. Вот тут и происходит маг c. В этом операторе действие emit (onNext) будет помещено в очередь как запускаемое в UI-eventl oop (AndroidSchedulers # mainThread).

Для получения дополнительных инструкций, пожалуйста, посмотрите это объяснение: http://tomstechnicalblog.blogspot.de/2016/02/rxjava-understanding-observeon-and.html

Проблема

Оператор #doAfterNext вызывается из потока, не относящегося к пользовательскому интерфейсу, который пытается изменить некоторое состояние пользовательского интерфейса.

Разрешение

Все изменения UI-состояния должны вызываться из UI-потока. Поэтому вы должны убедиться, что это так.

(application as? App)?.relayPages
                // observeOn switches the thread from X to the UI-eventloop
                ?.observeOn(AndroidSchedulers.mainThread())
                // hideLoading is called from UI-eventloop, everything should be fine
                ?.doAfterNext{
                    hideLoading()
                }

Сводка

ObserveOn должен быть помещен в цепочку операторов перед UI-состоянием изменено.

...