I'm trying to write an observable that would generate repeated events while the user holds down a view. My code below works well, but only the first time (e.g. if the user presses the button again, nothing happens). Can you please advise what am I doing wrong and what is best practice for this?
val touches = RxView.touches(previousButton)
touches
.filter({ event -> event.action == MotionEvent.ACTION_DOWN })
.flatMap({
Observable.interval(500, 50, TimeUnit.MILLISECONDS)
.takeUntil(touches.filter({event -> event.action == MotionEvent.ACTION_UP}))
}).subscribe({ println("down") })
The problem is that the RxView.touches
observable cannot exist for more than 1 source. This means when the subscription inside of the flatMap
happens it breaks the original subscription used to trigger the flatMap
, making it never occur again.
There are two possible ways around this:
.publish(...)
to share the source of events instead of using touches
.Boolean
on/off observable, then switchMap
the appropriate actions based on the current value of the observable.1.
touches.publish { src ->
src.filter(...)
.flatMap {
Observable.interval(...)
.takeUntil(src.filter(...))
}
}
2.
touches.filter {
it.action == MotionEvent.ACTION_DOWN
or it.action == MotionEvent.ACTION_UP
}
.map { it.action == MotionEvent.ACTION_DOWN }
.distinctUntilChanged() // Avoid repeating events
.switchMap { state ->
if (state) {
Observable.interval(...)
} else {
Observable.never()
}
}