Поймать количество кликов пользователя в промежутке времени с помощью RxJava

У меня есть приложение со скрытым меню отладки. Мне нужно включить это секретное меню, если (Build.DEBUG и) пользователь нажимает на представление, например, 4 раза за одну секунду. Я хотел бы использовать для этого RxJava.

Я попробовал DebouncedBuffer от Каушика Гопала в weddingpartyapp, но это подсчитывает клики и возвращает значение, если за указанный период времени не было кликов.

Я добился желаемого эффекта, используя простой buffer(), но он начинает буферизоваться и продолжает выдавать пустые списки, если нет кликов. Я могу добавить filter(), но я хотел бы добиться того же результата другим способом.

Я хотел бы запустить буфер после первого клика и собрать все клики (bufer()?) с заданным периодом времени (debounce()?), а затем остановить буферизацию. Я нашел buffer(bufferOpenings, bufferClosingSelector) введите здесь описание изображения

которые делают то, что мне нужно, и я нашел пример использования в Intro-To-RxJava, но это зависит от interval(). Как изменить это, чтобы первое наблюдаемое было первым значением в группе, а затем функция срабатывала через одну секунду от первого значения?

Кроме того, я нашел этот ответ, который добавляет проверку количества элементов (что тоже было бы полезно, потому что я могу остановить Observable после получаю 4 клика), но могу ли я добиться того же эффекта, не создавая новый Operator?


person Bresiu    schedule 16.12.2015    source источник


Ответы (2)


Найденный вами buffer — хорошее начало, но вам также нужен publish, чтобы разделить поток на два: один будет буферизоваться, чтобы увидеть, есть ли 4 клика, а другой будет действовать как триггер для открытия буферов с ограничением по времени:

PublishSubject<Integer> source = PublishSubject.create();
TestScheduler ts = Schedulers.test();

source.publish(p -> 
    p.buffer(p, o -> Observable.timer(1, TimeUnit.SECONDS, ts))
)
.filter(v -> v.size() == 4)
.subscribe(v -> System.out.println("Secret menu"));

System.out.println("Should open secret menu:");

source.onNext(1);
ts.advanceTimeBy(100, TimeUnit.MILLISECONDS);
source.onNext(1);
ts.advanceTimeBy(100, TimeUnit.MILLISECONDS);
source.onNext(1);
ts.advanceTimeBy(100, TimeUnit.MILLISECONDS);
source.onNext(1);
ts.advanceTimeBy(1000, TimeUnit.MILLISECONDS);


System.out.println("Should not open anything:");

source.onNext(1);
ts.advanceTimeBy(100, TimeUnit.MILLISECONDS);
source.onNext(1);
source.onNext(1);
ts.advanceTimeBy(1000, TimeUnit.MILLISECONDS);
source.onNext(1);
person akarnokd    schedule 17.12.2015
comment
Это именно то, что я ищу. Но могу ли я переключить 'p' Observable на RxView.clicks() в цепочке? Теперь у меня есть один Observable 'RxView.clicks (кнопка), который запускает 'source' PublishSubject 'onNext' - person Bresiu; 17.12.2015
comment
Просто используйте RxView.clicks(button).publish(...) напрямую и не заменяйте часть ... выше. - person akarnokd; 17.12.2015

Вот простой способ, который я нашел для этого:

fun <T> Observable<T>.debounceWithEvents(time:Long,timeUnit: TimeUnit) = takeUntil(debounce(time, timeUnit))

Он вернет наблюдаемую, которая генерирует все события, пока первое не будет отклонено. Надеюсь это поможет :)

person joaomgcd    schedule 18.12.2018