【问题标题】:Debouncing button clicks using Rx使用 Rx 去抖动按钮点击
【发布时间】:2015-09-10 09:35:56
【问题描述】:

我正在尝试制作一个简单的“按钮去抖动器”,它将计算过滤的点击次数并通过 TextView 显示它。我想过滤快速/垃圾邮件点击,以忽略中间间隔小于 300 毫秒的点击。

我进行了研究,偶然发现了 Rx 很棒的 debounce(),理论上它应该可以做我想做的事情..

..或者我是这么想的。由于该应用程序似乎只注册了第一次点击;无论我尝试等待多长时间,计数器都不会增加。

这是我的一段代码:

    ...

    RxView.clicks(mButton)
        .debounce(300, TimeUnit.MILLISECONDS)
        .subscribe(new Subscriber<Object>() {
            public int mCount;

            @Override
            public void onCompleted() {
            }

            @Override
            public void onError(Throwable e) {
            }

            @Override
            public void onNext(Object o) {
                mText.setText(String.valueOf(++mCount));
            }
        });

    ...

我做错了什么?我尝试在没有debounce() 的情况下运行该东西,并且它运行良好(每次单击按钮时计数器都会增加)。

提前致谢!

【问题讨论】:

    标签: android rx-java rx-android


    【解决方案1】:

    注意documentation on the debounce operator中的以下内容:

    默认情况下,此变体在计算调度程序(...)上运行

    或者,就代码而言,目前正在发生这种情况:

    public final Observable<T> debounce(long timeout, TimeUnit unit) {
        return debounce(timeout, unit, Schedulers.computation());
    }
    

    因此,订阅者的回调在同一个计算调度程序上被调用,因为没有明确的指示。

    现在,尝试从除 main/ui 线程之外的任何其他线程更新视图(onNext() 中正在发生的事情)是错误的,它会导致不确定的结果。

    幸运的是,上面引用的其余部分也提供了解决方案:

    (...) 但您可以选择传入您选择的调度程序作为第三个参数。

    这会导致:

    RxView.clicks(mButton)
        .debounce(300, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
        .subscribe(...);
    

    或者,您仍然可以让计算调度程序上发生去抖动,但在主/ui线程上接收通知:

    RxView.clicks(mButton)
        .debounce(300, TimeUnit.MILLISECONDS)
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(...);
    

    无论哪种方式都将确保在主/ui线程上接收通知,从而从正确的线程更新视图。

    【讨论】:

    • 最好使用throttleFirst而不是debounce
    • @wilddev:它是否“更好”取决于所需的行为,因为throttleFirstdebounce 不会产生相同的结果。我最初将这个问题解释为需要去抖动,但现在再读一遍,我同意throttleFirst 也可能有意义。我想这两个都是很好的候选人。无论如何,两者都在计算调度程序上运行,因此上述大部分内容都适用于任何一种方式。 :)
    • 为了“更好”,我的意思是如果使用 throttleFirst,您会立即获得点击反应,但使用 debounce 会有延迟。只是为了通知以后会发现这个问题的其他人:)
    • 是的,但由于throttleFirst 基本上是sample 的一种特定风格,它会通过每个 在某个周期性时间间隔内发出的第一个项目。 debounce 具有不同的行为,因为它仅在特定时间跨度已经过去 没有发出另一个项目的情况下才发出一个项目。细微差别:时间跨度与间隔。这可能与特定用例相关,也可能不相关。请注意这一点。
    • @MH。在 RxJava 1.x 中,throttleFirst 仅使用计算调度器的时间进行计算,但结果传递与即时调度器一样,未检查 Rx 2.x 源代码。
    猜你喜欢
    • 1970-01-01
    • 2017-12-16
    • 2013-03-10
    • 1970-01-01
    • 2017-01-16
    • 2019-04-18
    • 1970-01-01
    • 1970-01-01
    • 2021-07-04
    相关资源
    最近更新 更多