RxAndroid重复的ui操作任务错误

时间:2019-04-29 18:45:56

标签: android rx-java2 rx-android

我有以下代码来启用沉浸式模式。这是重复的任务,每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

我已将mainThread调度程序添加到delay()方法中,但是错误仍然存​​在。谁能告诉我我在做什么错?

1 个答案:

答案 0 :(得分:3)

此行:

.subscribeOn(Schedulers.io())

表示可调用中的代码将在IO线程上运行。 因此,第一次调用该方法时,它将在IO线程而不是主线程上。如果这不是您的意图,请删除该行。默认行为是,预订可观察对象的线程将是正在执行可调用对象中代码的线程。

此外,您在repeatWhen的延迟运算符中定义的调度程序是将用于延迟的调度程序,默认情况下为Schedulers.computation()。但是您永远都不会到达代码的这一部分,因为这是在初始订阅后可观察者重新订阅时使用的。但是在初始订阅中,由于您从IO线程访问UI,因此您的应用程序崩溃了。

如果您只希望此代码每1秒执行一次,则可以尝试以下操作:

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

请注意,此可观察的对象将重复出现,直到您告诉它停止为止。通过致电:

disposable.dispose()