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!
Asked
Active
Viewed 408 times
1
-
Is the method blocking or async? If async, which your question implies, how do you know when it's done? – AutonomousApps Sep 21 '18 at 05:42
-
@AutonomousApps It's async! And I'm fairly new at RxJava, but could I call my method somewhere in the chain and have it return a Completable.onCompelte()? I'm not sure where I'd call this method in the chain however or if this is a possible solution. – Sep 21 '18 at 05:58
2 Answers
1
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 }

Andrii Turkovskyi
- 27,554
- 16
- 95
- 105
1
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)
}

AutonomousApps
- 4,229
- 4
- 32
- 42