You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用RxBinding与RxJava实现按钮点击防重复请求的非ThrottleFirst方案

可选实现方案

下面三种方案均仅依赖RxJava和RxBinding实现,完全满足请求执行时忽略点击的需求:

方案1:使用exhaustMapSingle操作符(推荐)

exhaustMap系列操作符是专门应对这类场景的原生实现:只要当前内部请求流未完成,新的上游点击事件会被直接丢弃,不需要额外维护任何状态,代码侵入性最低。
修改后代码如下:

button.clicks()
        .exhaustMapSingle {
            Completable.fromCallable {
                usersViewModel.users(emptyList())
            }
                .andThen(Request.users())
        }
        .doOnNext {
            Toast
                .makeText(this, R.string.users_updated, Toast.LENGTH_LONG)
                .show()
        }
        .subscribe(usersViewModel::users) { Log.e(this::class.java.name, it.message, it) }

注:该操作符在RxJava 2.1及以上、RxJava 3全版本支持。

方案2:使用flatMapSingle的maxConcurrent参数

flatMap系列操作符均支持传入maxConcurrent参数限制同时订阅的内部流数量,将参数设为1时,后续的点击事件会被直接丢弃,效果和exhaustMapSingle完全一致。
修改后代码如下:

button.clicks()
        .flatMapSingle({
            Completable.fromCallable {
                usersViewModel.users(emptyList())
            }
                .andThen(Request.users())
        }, 1)
        .doOnNext {
            Toast
                .makeText(this, R.string.users_updated, Toast.LENGTH_LONG)
                .show()
        }
        .subscribe(usersViewModel::users) { Log.e(this::class.java.name, it.message, it) }

方案3:配合状态位用filter过滤点击

如果你的项目使用的RxJava版本较低不支持exhaustMap,可以手动维护请求状态位来过滤重复点击,兼容性最好。
实现代码如下:

// 标记请求是否正在执行
var isRequesting = false
button.clicks()
        // 仅请求未执行时响应点击
        .filter { !isRequesting }
        .flatMapSingle {
            isRequesting = true
            Completable.fromCallable {
                usersViewModel.users(emptyList())
            }
                .andThen(Request.users())
                // 无论请求成功失败都重置状态位
                .doOnEvent { _, _ -> isRequesting = false }
        }
        .doOnNext {
            Toast
                .makeText(this, R.string.users_updated, Toast.LENGTH_LONG)
                .show()
        }
        .subscribe(usersViewModel::users) { Log.e(this::class.java.name, it.message, it) }

注意:必须在请求的最终回调里重置状态位,避免请求报错后按钮永久无法点击。


内容的提问来源于stack exchange,提问作者Ahmadreza Zarei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 06:18:03