RxJava Observable 在按钮按下时生成重复事件
RxJava Observable to generate repeated events when button is down
我正在尝试编写一个可观察对象,它会在用户按住视图时生成重复事件。我下面的代码运行良好,但只是第一次(例如,如果用户再次按下按钮,什么也没有发生)。你能告诉我我做错了什么吗?最佳做法是什么?
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") })
问题是 RxView.touches
observable 不能存在超过 1 个源。这意味着当 flatMap
内的订阅发生时,它会破坏用于触发 flatMap
的原始订阅,使其不再发生。
有两种可能的解决方法:
- 使用
.publish(...)
来共享事件源,而不是使用 touches
。
- 将事件映射到
Boolean
on/off 可观察对象,然后 switchMap
根据可观察对象的当前值采取适当的操作。
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()
}
}
我正在尝试编写一个可观察对象,它会在用户按住视图时生成重复事件。我下面的代码运行良好,但只是第一次(例如,如果用户再次按下按钮,什么也没有发生)。你能告诉我我做错了什么吗?最佳做法是什么?
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") })
问题是 RxView.touches
observable 不能存在超过 1 个源。这意味着当 flatMap
内的订阅发生时,它会破坏用于触发 flatMap
的原始订阅,使其不再发生。
有两种可能的解决方法:
- 使用
.publish(...)
来共享事件源,而不是使用touches
。 - 将事件映射到
Boolean
on/off 可观察对象,然后switchMap
根据可观察对象的当前值采取适当的操作。
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()
}
}