Debouncing button clicks using Rx

岁酱吖の 提交于 2020-02-23 09:37:05

问题


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.

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.

Here's a piece of my code:

    ...

    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));
            }
        });

    ...

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).

Thanks in advance!


回答1:


Note the following in the documentation on the debounce operator:

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.

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.

This would lead to:

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

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(...);

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.



来源:https://stackoverflow.com/questions/32498210/debouncing-button-clicks-using-rx

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!