RxJava - how to call a subscriber on 4 click events in Android

In android, I have a text view defined as follows:

<TextView android:id="@+id/text1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" android:textColorHighlight="#000000" android:textIsSelectable="true" /> 

My goal is that after clicking 4 times, I want to start a new job. I need to do this using RXJava; this is a requirement. Or rxAndroid , rxBinding , etc.

My activity is as follows:

 public class MainActivity extends Activity implements onClickListener { TextView tv; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv=(TextView)findViewById(R.id.text1); tv.setOnClickListener(this); } @Override public void onClick(View v) { if(v.getId() == R.id.text1){ } } } 

UPDATE: but this is just the standard way to do this. With reactive rxJava API there should be a way.

So, instead of using onClicklistener with rxBinding , I read that we can do this:

 RxView.clicks(tv).flatMap(tv -> { // another observable which can throw onError. return Observable.error(null); }).subscribe(object -> { Log.d("CLICK", "textview clicked", start activity); }, error -> { Log.d("CLICK", "ERROR"); }); 

Is there any way to use the command in rxBinding to execute it only after 4 clicks? I do not want to store a static variable or use an anonymous class and store a member variable for counting. There must be an observable method for this.

+5
source share
5 answers

You can create an observable to radiate every time the button is pressed, then count the total amount of time it has taken and use a filter so that your subscriber sees it only after it has emitted four times.

 Observable<View> buttonObservable = ViewObservable.clicks(initiateButton, false); buttonObservable.count() .filter(count -> (count >= 4)) .subscribe(object -> { //Your code here }); 
+2
source

You can achieve something like this:

 Observable.create((Observable.OnSubscribe<Void>) subscriber -> { if (!subscriber.isUnsubscribed()) { button.setOnClickListener(v -> subscriber.onNext(null)); } }).buffer(1000, TimeUnit.MILLISECONDS) .filter(clicks -> clicks.size() == 4) .observeOn(AndroidSchedulers.mainThread()) .subscribe(clicks -> { Log.d("CLICK", "CLICK"); }); 
  • buffer() - collect clicks for window 1s
  • filter() - filter all emitted buffered elements, where the number of elements in the buffer is not equal to 4 (disable double, triple, fivefold clicks)

The hardest part is to specify the window buffer time. One second is sometimes not enough, but in other cases the user has to wait a few milliseconds.

+5
source

@skywall's answer is the most comprehensive, however, if you do not need time intervals, the simplest answer would be to use skip

 Observable<Void> fourClicksView = RxView.clicks(tv).skip(3); fourClicksView.subscribe(...); 
+1
source

If you want to start an action after a certain number of clicks in the time window, try the following:

 RxView.clicks(tv) .map(e -> SystemClock.elapsedRealtime()) .buffer(NUM_CLICKS, 1) //Grab every sub-sequence of however many clicks .filter(times -> times.size() == NUM_CLICKS) //Last values will be truncated .filter(times -> times.get(NUM_CLICKS - 1) - times.get(0) < ALLOWED_TIME) //check times .subscribe(ignore -> startActivity()); 
0
source

Use buffer and debounce command.

 val clickStream = RxView.clicks(view) clickStream.buffer(clickStream.debounce(250, TimeUnit.MILLISECONDS)) .map { it.size } .filter { it == 4 } .subscribe({ }) 
0
source

Source: https://habr.com/ru/post/1240932/


All Articles