RxAndroid повторил ошибку задачи пользовательского интерфейса манипуляции - PullRequest
0 голосов
/ 29 апреля 2019

У меня есть следующий код для включения режима погружения. Это повторяющаяся задача, которая выполняется каждую 1 секунду:

Completable
                        .fromAction(() -> {
                                if (uiSystemVisibility == 0) enableImmersiveMode();
                        })
                        .subscribeOn(Schedulers.io())
                        .repeatWhen(objectFlowable -> objectFlowable.delay(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread()))
                        .subscribe();

enableImmersiveMode ():

public void enableImmersiveMode() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
        return;
    }

    getWindow().getDecorView().setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_IMMERSIVE);
}

Когда вызывается enableImmersiveMode (), я получаю следующую ошибку:

Only the original thread that created a view hierarchy can touch its views

Я добавил в метод delay () планировщик mainThread для работы, но ошибка сохраняется. Может кто-нибудь сказать мне, что я делаю неправильно?

1 Ответ

3 голосов
/ 29 апреля 2019

Эта строка:

.subscribeOn(Schedulers.io())

означает, что код в вашей вызываемой программе будет выполняться в потоке ввода-вывода.Таким образом, в первый раз этот метод вызывается в потоке ввода-вывода, а не в основном потоке.Удалите эту строку, если это не ваше намерение.Поведение по умолчанию состоит в том, что какой-либо поток, который подписывается на наблюдаемое, будет потоком, выполняющим код в вашем вызываемом объекте.

Кроме того, планировщик, который вы определяете в операторе задержки repeatWhen является планировщиком, который будет использоваться длязадержка и по умолчанию это Schedulers.computation ().Но вы никогда не достигнете этой части кода, поскольку это происходит, когда наблюдаемое повторно подписывается после первоначальной подписки.Но в начальной подписке ваше приложение вылетает из-за того, что вы обращаетесь к пользовательскому интерфейсу из потока ввода-вывода.

Если вы просто хотите, чтобы этот код выполнялся каждую 1 секунду, вы можете попробовать это:

val disposable = Observable.interval(1, TimeUnit.SECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    if (uiSystemVisibility == 0) enableImmersiveMode();
                }

Имейте в виду, что эта наблюдаемая будет повторяться до тех пор, пока вы не скажете ей остановиться.Сделайте это, позвонив по номеру:

disposable.dispose()
...