Android Retrofit+RxJava无法发起多次重复网络请求问题
问题原因
当前代码仅会触发单次网络请求:Retrofit搭配RxJava2返回的是单次执行的冷流,请求完成(无论成功还是失败)后流就会直接终止,代码里没有配置重复执行、间隔触发、错误重试、终止退出的轮询逻辑,自然达不到重复轮询接口的效果。
修改方案
轮询逻辑需要实现四个核心能力:固定间隔发起请求、单次请求报错不中断整体轮询、拿到目标结果后自动停止、绑定页面生命周期防止内存泄漏,具体修改如下:
1. 调整Activity中的payment方法
首先在Activity中定义订阅持有对象和轮询间隔配置,修改后的完整代码如下:
// 持有轮询订阅,用于主动停止任务、页面销毁时取消任务防止泄漏 private var pollDisposable: Disposable? = null // 轮询间隔,单位毫秒,建议设置1-3秒,避免请求过于频繁 private val POLL_INTERVAL = 2000L private fun payment(id: String) { val repository = SearchRepositoryProvider.provideSearchRepository() // 启动新轮询前先取消上一轮可能存在的任务,避免重复请求 pollDisposable?.dispose() pollDisposable = Observable.interval(0, POLL_INTERVAL, TimeUnit.MILLISECONDS) .flatMap { repository.searchUsers(id) // 单次请求报错(包括5秒超时、网络波动)时返回空,不中断整个轮询流 .onErrorResumeNext(Observable.empty()) } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ status -> if (status == "succeeded") { // 拿到支付成功状态,先终止轮询 pollDisposable?.dispose() // 此处编写支付成功后的业务逻辑 // do staff } // 非成功状态无需额外处理,等待下一轮轮询即可 }, { error -> Log.i(TAG, error.message ?: "轮询执行异常") }) } // 必须在页面销毁时取消轮询,避免内存泄漏、空指针崩溃 override fun onDestroy() { super.onDestroy() pollDisposable?.dispose() }
关键逻辑说明
Observable.interval(0, POLL_INTERVAL, TimeUnit.MILLISECONDS)用于实现定时触发:第一个参数传0代表订阅后立刻发起第一次请求,之后每隔设定的间隔时间触发下一次请求onErrorResumeNext(Observable.empty())是保证轮询不中断的核心:你已经给OkHttp配置了5秒超时,一旦某次请求超时、网络波动报错,不会直接走到订阅的error回调终止整个轮询,而是跳过本次失败请求,等下一个周期继续尝试- 主动持有
Disposable是轮询场景的必要操作:轮询是长时间运行的异步任务,如果不绑定页面生命周期,Activity退出后任务仍会在后台执行,会引发内存泄漏、空指针崩溃 - 拿到
succeeded状态后立刻调用dispose()终止流,避免发起无意义的多余请求
可选优化
- 如果需要限制轮询最大时长(比如最多轮询2分钟,超时就提示用户支付超时),可以把
interval替换为intervalRange,指定最大发射次数,到达次数后自动停止轮询,走超时提示逻辑 - 可以在错误处理中增加异常类型判断:如果是断网等明确无法继续请求的错误,直接终止轮询提示用户检查网络;如果是超时、服务端5xx错误则继续下一轮轮询
- 你之前配置的OkHttp 5秒超时无需修改,配置合理,单次请求超时后等待下一轮重试即可
内容的提问来源于stack exchange,提问作者prosyanoy
相关产品推荐
相关产品推荐

