2015-09-10 8 views
5

私は単純な「ボタンデバウンサー」を作っています。これは、フィルタリングされたクリックをカウントし、TextViewを通して表示します。私は300ms以下の時間間隔でクリックが無視されるように、急速な/スパムのクリックをフィルタリングしたいと思います。 Rxを使用したボタンクリックのデバウンス

が、私は私の研究を行なったし、つまずい Rxの理論で私が望んでいた正確なことを行う必要があります debounce()素晴らしい..

は..orので、私は思いました。アプリは最初のクリックを登録するように見えたので、私がどれくらい待っても、カウンタは増えません。

は、ここに私のコードの一部です:私は間違って

... 

    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()せずにその事を実行しようとしたが、それは完璧に機能した(カウンタは、ボタンがクリックされたたびに増加する)。

ありがとうございます!

答えて

15

注意documentation on the debounce operatorでは、以下の項目をこの変種は、演算スケジューラ(...)

あるいは、コードごとにデフォルトで動作し

、これは現在起き:

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

結果として、明示的に何も指示していないので、加入者のコールバックは同じ計算スケジューラで呼び出されます。

ここで、メイン/ uiスレッド以外のスレッドからビュー(これはonNext()で発生している)を更新しようとすると間違いが起こり、結果が不定になります。 (...)

ていますが、必要に応じて第三パラメータとして、あなたが選んだのスケジューラに渡すことができます。

幸いなことに、上記の引用の残りの部分は、あまりにもソリューションを提供します。これはにつながる

:また

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

、あなたはまだデバウンスは、演算スケジューラに身を任せるが、メイン/ UIスレッドで通知を受け取ることができます。

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

どちらの方法でも、メイン/ uiスレッドで通知が受信され、ビューが正しいスレッドから更新されます。

+1

デバッグの代わりにthrottleFirstを使用する方が良いでしょう。 – wilddev

+0

@wilddev:「より良い」かどうかは、 'throttleFirst'と' debounce'が同じ結果をもたらさないため、望ましい動作に依存します。私は最初にデバウンスを要求するように解釈しましたが、もう一度それを読むと、throttleFirstも理にかなっていることに同意します。私は両方の良い候補者を作ると思います。いずれにせよ、どちらも計算スケジューラ上で動作するため、上記のほとんどがいずれにも適用されます。 :) –

+0

"良い"の意味では、throttleFirstの場合はすぐにクリック反応が出ますが、デバウンスには遅れがあります。 – wilddev

関連する問題