user7281939
user7281939

Reputation:

RxJava 2 - How do you only do an action for first click event, and then restart after event occurs?

I have a button. If a user presses on it several times, I want it to run a method only when it receives the first click. After the method is finished running and done, I want to listen for button clicks again and do the action only when we receive the first click... ignore the other clicks (continue repeating this). How do I accomplish this with RxJava 2? I don't want to use things along the lines of firstElement() because it will make the button unusable after the first click. Thanks!

Upvotes: 1

Views: 515

Answers (2)

AutonomousApps
AutonomousApps

Reputation: 4389

Here's an approach that doesn't require a secondary field to track anything, but that doesn't necessarily make it better.

clicks() is from Jake Wharton's RxBinding library. You can get the Observable however you like.

button.clicks()
    // not strictly necessary, since we disable the button
    .filter { button.isEnabled }
    .doOnNext { button.isEnabled = false }
    .observeOn(Schedulers.computation()) // or io() or whatever
    .flatMap { doThing() }
    .observeOn(AndroidSchedulers.mainThread())
    // `each` instead of `next` so this also consumes errors
    .doOnEach { button.isEnabled = true }
    .subscribe()

private fun doThing(): Observable<Int> {
    // simulate long-running op
    Thread.sleep(2000)
    // return any value; doesn't matter
    return Observable.just(0)
}

Upvotes: 1

Andrii Turkovskyi
Andrii Turkovskyi

Reputation: 29468

Actually, not the best solution, but it can help - you can save state of your action. Something like this:

var isActionDone = true

buttonObservable
.filter { isActionDone }
.flatMap {
   isActionDone = false
   youActionCompletable
}
.subscribe { isActionDone = true }

Upvotes: 1

Related Questions