我想以这样的方式转换我的源Flowable,即只要它们是指定时间段内的第一个项目,事件才会发生。
也就是说,我希望第一个项目通过然后删除所有后续项目,直到有一段时间,比如10秒,其中没有上游事件到达。
请注意,这不是
debounce
:如果没有其他一个项目持续10秒钟,这会发出每个项目 - 但这会迫使第一个项目延迟10秒。我想立即发出第一个项目。throttleFirst
:这将发出第一个项目,然后在第一个项目之后丢弃所有后续项目10秒。我希望在每个上游项目之后重置阻塞时段。我现在已经解决了这个问题:
source
.flatMap { Flowable.just(1).concatWith(Flowable.just(-1).delay(10, TimeUnit.SECONDS)) }
.scan(0, { x, y -> x + y })
.map { it > 0 }
.distinctUntilChanged()
.filter { it }
注意:我并不关心source
中的实际项目,只关注它们 - 但当然,我可以将项目与Pair
一起包裹在1
中1}}或-1
)。
是否有更简单的方法使用内置的RxJava(2)运算符来实现相同的目标?
答案 0 :(得分:2)
可以使用switchMap
一次仅订阅一个Flowable
并使用布尔值检查是否必须发出的事实:
class ReduceThrottle<T>(val period: Long, val unit: TimeUnit) : FlowableTransformer<T, T> {
override fun apply(upstream: Flowable<T>): Publisher<T> {
return Flowable.defer {
val doEmit = AtomicBoolean(true)
upstream.switchMap { item ->
val ret = if (doEmit.compareAndSet(true, false)) {
// We haven't emitted in the last 10 seconds, do the emission
Flowable.just(item)
} else {
Flowable.empty()
}
ret.concatWith(Completable.timer(period, unit).andThen(Completable.fromAction {
// Once the timer successfully expires, reset the state
doEmit.set(true)
}).toFlowable())
}
}
}
}
然后,只需应用变压器:source.compose(ReduceThrottle(10, TimeUnit.SECONDS))
。
答案 1 :(得分:-1)
这可能会做你需要的事情
source.debounce(item -> Observable.timer(10,TimeUnit.SECONDS))