2015-09-10 10 views
5

Próbuję zrobić prosty "przycisk debouncer", który zliczy kliknięcia filtrowane i wyświetli je poprzez TextView. Chcę filtrować kliknięcia typu "szybki/spam" w taki sposób, że kliknięcia z mniej niż 300ms odstępu czasu pomiędzy nimi są ignorowane.Kliknięcia przycisku rozwijania za pomocą Rx

zrobiłem moje badania i natknął ..or więc pomyślałem Rx „s niesamowite debounce() który teoretycznie powinien zrobić dokładną rzeczą, jaką chciałem ..

. Ponieważ aplikacja zdawała się rejestrować tylko pierwsze kliknięcie; licznik nie będzie wzrastał bez względu na to, jak długo starałem się czekać.

Oto fragment mojego kodu:

... 

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

    ... 

Co robię źle? Próbowałem uruchomić to bez debounce() i działało bezbłędnie (licznik będzie się zwiększał za każdym razem, gdy przycisk zostanie kliknięty).

Z góry dziękuję!

Odpowiedz

15

Uwaga następujące w documentation on the debounce operator:

Wariant ten działa domyślnie w Harmonogramie obliczeń (...)

Lub kod mądry, to obecnie dzieje:

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

W wyniku tego wywołania zwrotne subskrybenta są wywoływane w tym samym programie planującym obliczenia, ponieważ nic nie wskazuje wyraźnie inaczej.

Teraz próba zaktualizowania widoku (to dzieje się w onNext()) z dowolnego innego wątku niż wątek główny/ui, jest błędem i doprowadzi do nieokreślonych wyników.

szczęście pozostała część cytatu powyżej rozwiązanie zapewnia też:

(...), ale opcjonalnie można przekazać w Harmonogramie swojego wyboru jako trzeci parametr.

będzie to prowadzić do:

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

Ewentualnie można jeszcze niech nieczułości zdarzyć na scheduler obliczeń, ale odbierać powiadomienia na głównym wątku/ui:

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

Tak czy inaczej zapewni, że powiadomienia są odbierane w wątku głównym/ui, a tym samym, że widok jest aktualizowany z właściwego wątku.

+1

Lepiej używać throttleFirst zamiast debounce – wilddev

+0

@wilddev: to, czy jest "lepsze" czy nie, zależy od pożądanego zachowania, ponieważ 'throttleFirst' i' debounce' nie dają tego samego wyniku. Pierwotnie zinterpretowałem pytanie wymagające debounce, ale czytając to ponownie teraz, zgadzam się, że throttleFirst może również mieć sens. Myślę, że to jest dobry kandydat. Niezależnie od tego, oba działają w programie planującym obliczenia, więc większość z nich ma zastosowanie w dowolny sposób. :) –

+0

Dla "lepszego" mam na myśli to, że w przypadku przepustnicy Najpierw masz reakcję kliknięcia, ale z opóźnieniem pojawia się opóźnienie.Po prostu, aby poinformować innych, którzy znajdą to pytanie później :) – wilddev

Powiązane problemy