Kotlin中RXJava请求失败后,点击重试按钮重发请求的方案咨询
修复SnackBar重试按钮触发请求的问题
嘿,咱们来一步步拆解你的问题,把这个重试逻辑修好~首先看你当前的代码,核心问题出在retryWhen的逻辑关联上——你错误用了itemClickObserver而非重试按钮对应的_retryClickObserver,导致点击信号根本没传到重试流里,另外zipWith的用法也不符合「错误后等待重试点击」的需求,咱们逐个解决:
方案一:修正retryWhen逻辑(贴合你原本的RxJava思路)
先调整Presenter里的retryWhen部分,把错误流和重试点击流正确绑定:
fun loadData() { addSubscription(repository.getData() .doOnSubscribe { view.showProgressBar() } .doAfterTerminate { view.hideProgressBar() } .retryWhen { errors -> // 每个错误发生后,等待一次重试点击再触发重试 errors.flatMap { _ -> _retryClickObserver .take(1) // 确保每次错误只响应一次重试点击 .doOnNext { /* 可选:加日志确认重试信号触发 */ } } } .subscribe({ handleResult(it) }, { handleError(it) } ) ) }
然后优化View与Presenter的交互(遵循MVP分层原则,不要直接暴露Subject给View):
在Presenter里新增公开方法:
fun onRetryClicked() { _retryClickObserver.onNext(Unit) }
Fragment里调用这个方法:
override fun showErrorMessage() { showSnackBar(rootLayout, R.string.try_again) { presenter.onRetryClicked() } }
方案二:简化逻辑——直接重新调用loadData(适合简单场景)
如果你的重试逻辑不需要复杂的Rx流控制,直接点击按钮时重新调用loadData()会更直观:
- 移除Presenter里所有
_retryClickObserver相关代码 - 调整Fragment的点击回调:
override fun showErrorMessage() { showSnackBar(rootLayout, R.string.try_again) { presenter.loadData() } }
⚠️ 注意:要确保loadData()可安全重复调用,每次调用前取消之前的订阅,避免多请求并行或内存泄漏:
private val compositeDisposable = CompositeDisposable() fun loadData() { // 先清空之前的订阅 compositeDisposable.clear() val subscription = repository.getData() .doOnSubscribe { view.showProgressBar() } .doAfterTerminate { view.hideProgressBar() } .subscribe({ handleResult(it) }, { handleError(it) } ) compositeDisposable.add(subscription) }
方案三:检查线程调度(避免信号丢失)
如果上面的方案还是没生效,可能是线程调度问题——比如点击事件在主线程发送,但Rx流在IO线程运行,需要确保重试信号在正确线程传递:
.retryWhen { errors -> errors.flatMap { _ -> _retryClickObserver .take(1) .subscribeOn(AndroidSchedulers.mainThread()) // 监听主线程的点击事件 .observeOn(Schedulers.io()) // 切换到请求执行的线程 } }
优先试试方案一,这是贴合你原本RxJava重试思路的修复;如果场景不需要复杂流控制,方案二会更简单易维护。
内容的提问来源于stack exchange,提问作者santosh kumar
相关产品推荐
相关产品推荐

