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

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()会更直观:

  1. 移除Presenter里所有_retryClickObserver相关代码
  2. 调整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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 07:07:37