纯RxJava实现防快速点击问题:blockingSubscribe未触发
纯RxJava实现防快速点击:问题分析与解决方案
我来帮你梳理下问题根源,以及纯RxJava下的正确实现方式:
为什么你的代码没生效?
你现在的写法是每次点击都新建一个独立的Observable流,而throttleLast的作用范围是单个流内的连续事件。每个Observable.just(time)只发射一个事件就立刻结束了,throttleLast需要等待500ms的窗口时间,但流已经提前完成,根本不会触发订阅里的逻辑。
正确的实现思路
要实现防快速点击,必须把所有点击事件都汇入同一个共享的Observable流,这样throttleLast才能对连续的点击进行节流控制。我们可以用PublishSubject来做这个共享流,具体步骤如下:
1. 定义全局的共享Subject
在你的类(比如Activity、Fragment或者ViewModel)里声明一个全局的PublishSubject,用来接收所有点击事件:
private val clickSubject = PublishSubject.create<Long>()
2. 初始化节流订阅
在类的初始化阶段(比如Activity的onCreate方法),给这个Subject添加throttleLast操作符并订阅,这样所有流入的点击事件都会被统一节流:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ...其他初始化代码 clickSubject .throttleLast(500, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) // 如果需要在UI线程处理逻辑就加这个 .subscribe { clickTime -> Timber.d("处理点击事件,时间戳:%s", clickTime) // 这里写你的点击业务逻辑 } }
3. 点击时发送事件到Subject
修改点击方法,不再每次创建新Observable,而是把点击时间戳发送到共享的Subject里:
fun previousDateOnClick(view: View) { val time = System.currentTimeMillis() Timber.d("previousButtonClick time=%s", time) clickSubject.onNext(time) }
4. 别忘了清理订阅避免内存泄漏
如果是在Activity/Fragment中使用,记得在生命周期销毁时取消订阅:
private var clickDisposable: Disposable? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... clickDisposable = clickSubject .throttleLast(500, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe { clickTime -> Timber.d("处理点击事件,时间戳:%s", clickTime) } } override fun onDestroy() { super.onDestroy() clickDisposable?.dispose() }
额外提醒
- 不要用
blockingSubscribe,它会阻塞当前线程(UI线程),导致界面卡顿,用普通的subscribe就好。 - 如果你的业务逻辑需要在UI线程执行,一定要加上
observeOn(AndroidSchedulers.mainThread())。
内容的提问来源于stack exchange,提问作者Sai
相关产品推荐
相关产品推荐

