使用 Rx 去抖按钮点击
Debouncing button clicks using Rx
我正在尝试制作一个简单的 "button debouncer",它将计算过滤后的点击次数并通过 TextView 显示它。我想过滤 rapid/spam 次点击,忽略间隔小于 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()
的东西并且它完美地工作(每次点击按钮时计数器都会增加)。
提前致谢!
注意 documentation on the debounce operator 中的以下内容:
This variant operates by default on the computation Scheduler (...)
或者,代码方面,当前发生的是:
public final Observable<T> debounce(long timeout, TimeUnit unit) {
return debounce(timeout, unit, Schedulers.computation());
}
因此,订阅者的回调在同一个计算调度程序上被调用,因为没有任何其他明确指示。
现在,尝试从 main/ui 线程以外的任何其他线程更新视图(这就是 onNext()
中发生的事情)是错误的,它会导致不确定的结果。
幸运的是,上面引用的其余部分也提供了解决方案:
(...) 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(...);
或者,您仍然可以让去抖动发生在计算调度程序上,但在 main/ui 线程上接收通知:
RxView.clicks(mButton)
.debounce(300, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(...);
任何一种方式都将确保在 main/ui 线程上收到通知,从而确保从正确的线程更新视图。
我正在尝试制作一个简单的 "button debouncer",它将计算过滤后的点击次数并通过 TextView 显示它。我想过滤 rapid/spam 次点击,忽略间隔小于 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()
的东西并且它完美地工作(每次点击按钮时计数器都会增加)。
提前致谢!
注意 documentation on the debounce operator 中的以下内容:
This variant operates by default on the computation Scheduler (...)
或者,代码方面,当前发生的是:
public final Observable<T> debounce(long timeout, TimeUnit unit) {
return debounce(timeout, unit, Schedulers.computation());
}
因此,订阅者的回调在同一个计算调度程序上被调用,因为没有任何其他明确指示。
现在,尝试从 main/ui 线程以外的任何其他线程更新视图(这就是 onNext()
中发生的事情)是错误的,它会导致不确定的结果。
幸运的是,上面引用的其余部分也提供了解决方案:
(...) 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(...);
或者,您仍然可以让去抖动发生在计算调度程序上,但在 main/ui 线程上接收通知:
RxView.clicks(mButton)
.debounce(300, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(...);
任何一种方式都将确保在 main/ui 线程上收到通知,从而确保从正确的线程更新视图。