使用 Rx 消除按钮点击 [英] Debouncing button clicks using Rx

查看:45
本文介绍了使用 Rx 消除按钮点击的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to make a simple "button debouncer" which will count filtered clicks and display it thru a TextView. I want to filter rapid/spam clicks in a way that clicks with less than 300ms time-gap in-between are ignored.

我做了我的研究并偶然发现了 Rx 很棒的 debounce() 理论上应该可以做我想要的确切的事情..

I did my research and stumbled upon Rx's awesome debounce() which in theory should do the exact thing I wanted..

……我是这么想的.由于该应用程序似乎只记录了第一次点击;无论我尝试等待多久,计数器都不会增加.

..or so I thought. As the app seemed to only register the first click; the counter won't increment no matter how long I tried to wait.

这是我的一段代码:

    ...

    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() 的情况下运行这个东西,它完美地工作(每次点击按钮时计数器都会增加).

What am I doing wrong? I've tried to run the thing without debounce() and it worked flawlessly (the counter will increment everytime the button got clicked).

提前致谢!

推荐答案

请注意 关于去抖动运算符的文档:

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

This variant operates by default on the computation Scheduler (...)

或者,在代码方面,这目前正在发生:

Or, code-wise, this currently happens:

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

因此,订阅者的回调是在同一个计算调度器上调用的,因为没有明确指示否则.

As a result, the subscriber's callbacks are invoked on that same computation scheduler, since nothing is explicitly instructing otherwise.

现在,尝试从 main/ui 线程以外的任何其他线程更新视图(这就是 onNext() 中发生的事情)是一个错误,它将导致不确定的结果.

Now, attempting to update a view (that's what's happening in onNext()) from any other thread than the main/ui thread, is a mistake and it will lead to undetermined results.

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

Fortunately, the remainder of the quote above provides the solution too:

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

(...) but you can optionally pass in a Scheduler of your choosing as a third parameter.

这将导致:

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

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

Alternatively, you can still let the debounce happen on the computation scheduler, but receive the notifications on the main/ui thread:

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

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

Either way will ensure that the notifications are received on the main/ui thread and thus that the view is updated from the correct thread.

这篇关于使用 Rx 消除按钮点击的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆