使用Rx去除按钮单击

MrH*_*rio 6 android rx-java rx-android

我正在尝试制作一个简单的"按钮去抖动器",它将计算过滤后的点击次数并通过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));
            }
        });

    ...
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?我试图在没有debounce()它的情况下运行它并且它完美地工作(每次按下按钮时计数器都会增加).

提前致谢!

MH.*_*MH. 20

请注意debounce运算符文档中的以下内容:

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

或者,代码方面,这当前发生:

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

结果,在同一计算调度器上调用订户的回调,因为没有任何明确指示.

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

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

(...)但您可以选择将您选择的计划程序作为第三个参数传递.

这将导致:

RxView.clicks(mButton)
    .debounce(300, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
    .subscribe(...);
Run Code Online (Sandbox Code Playgroud)

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

RxView.clicks(mButton)
    .debounce(300, TimeUnit.MILLISECONDS)
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(...);
Run Code Online (Sandbox Code Playgroud)

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

  • 最好使用throttleFirst而不是debounce (4认同)
  • 对于“更好”,我的意思是,在使用 ThrottleFirst 的情况下,您会立即获得点击反应,但使用 debounce 会出现延迟。只是为了通知以后会发现这个问题的其他人:) (2认同)