Preventing rapid clicks on a button and making a request using rxjava

Bascially, what I am looking for if the user rapidly clicks on the button within 300 milliseconds duration it should accept the last click in that duration

to me sounds more like that debounce operator behaviour. From the documentation

Debounce — only emit an item from an Observable if a particular timespan has passed without it emitting another item

you can see the marble diagram here


private val subject = PublishSubject.create<String>()

init {
    processClick()
}

fun onClick(name: String) {
    subject.onNext(name)
}

private fun processClick() {
    subject
        .debounce(300, TimeUnit.MILLISECONDS)
        .switchMap { getPokemonDetailByName(it) }
        .subscribe(
            { pokemonDetailLiveData.value = it },
            { Timber.e(TAG, it.localizedMessage) }
        )
}

private fun getPokemonDetailByName(name: String): Observable<Pokemon> =   
     pokemonDetailInteractor
        .getPokemonDetailByName(name)
        .subscribeOn(pokemonSchedulers.background())
        .observeOn(pokemonSchedulers.ui())
        .toObservable()

In your case, the getPokemonDetailByName creates a new subscription every time. Instead, send the click events to a Subject, create a single subscription to that stream and apply debounce.


I think you should handle click events as an observable so you can call debounce on clicks themselves. One way to achieve what you look for is to have a class creating an observable from the view being clicked:

public class RxClickObservable {

    public static Observable<String> fromView(View view, String pokemonName) {

        final PublishSubject<String> subject = PublishSubject.create();

        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                subject.onNext(pokemonName);
            }
        });

        return subject;
    }

}

and in activity/fragment:

RxClickObservable.fromView(binding.button, pokemonName)
        .subscribeOn(pokemonSchedulers.background())
        .observeOn(pokemonSchedulers.ui())
        .debounce(300, TimeUnit.MILLISECONDS)
        .switchMap(pokemonName ->  pokemonDetailInteractor.getPokemonDetailByName(pokemonName))
        .subscribe(... );

Update: Thanks to Amit Shekhar for this article: Implement Search Using RxJava Operators