Android中RxJava debounce操作符未触发问题求助
RxJava debounce操作符未触发的问题排查与解决
尝试使用debounce操作符处理频繁触发的事件,通过无限定时器模拟周期性事件,但debounce始终未被调用,代码如下:
val slower = PublishSubject.create<Int>() fun setup() { slower .debounce(3, TimeUnit.SECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe { Timber.d("test slower $it") //this never called }.addTo(disposable) // run 1 sec endless timer Observable.interval(0, 1000, TimeUnit.MILLISECONDS) .subscribeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe { Timber.d("test timer 1 sec") slower.onNext(1) }.addTo(disposable) }
build.gradle:
// RxJava implementation 'io.reactivex.rxjava2:rxjava:2.2.10' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' // RxKotlin implementation 'io.reactivex.rxjava2:rxkotlin:2.4.0'
问题核心出在debounce的工作逻辑上:debounce会等待你指定的时间(这里是3秒),只有当这段时间内没有新事件发送时,才会把最后收到的事件发射给下游。
你现在用Observable.interval每秒就给slower发送一次事件,相当于每过1秒就重置了debounce的3秒等待窗口,永远等不到"3秒内无新事件"的触发条件,所以下游的订阅回调自然不会执行。
解决方案
根据你的实际需求,有两种常见处理方式:
- 如果想每3秒处理一次事件:改用
throttleFirst或throttleLast操作符。throttleFirst(3, TimeUnit.SECONDS)会在每3秒的时间窗口内发射第一个事件,throttleLast则发射窗口内的最后一个事件,示例代码:
slower .throttleFirst(3, TimeUnit.SECONDS) // 替换debounce为throttleFirst .observeOn(AndroidSchedulers.mainThread()) .subscribe { Timber.d("test slower $it") }.addTo(disposable)
- 一定要用debounce的话:需要让事件流出现至少3秒的停顿,比如修改定时器间隔为大于3秒,或者在特定条件下暂停发送事件,这样debounce的等待窗口才能走完,示例:
// 修改定时器间隔为4秒,这样debounce的3秒窗口会在第4秒到来前触发 Observable.interval(0, 4000, TimeUnit.MILLISECONDS) .subscribeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe { Timber.d("test timer 4 sec") slower.onNext(1) }.addTo(disposable)
内容的提问来源于stack exchange,提问作者Konstantin Konopko
相关产品推荐
相关产品推荐

