Android开发中如何为Option的getOrElse函数设置请求重试最大次数
问题根因
当前出现无限重试的核心原因:
- 重试链路没有携带重试次数的状态标记,每次命中请求失败分支时,都会无差别调用无参的
sendRequest()发起新请求,没有任何终止判断 - 原有逻辑把Option的结果映射、Single的异步切换、重试触发三类逻辑混写在一起,代码结构错位:
option.map块内部返回的是Single类型,和Option原本的BeResponse泛型不匹配,getOrElse的触发逻辑也和内部错误判断完全脱节,没有有效拦截重试行为
另外原代码存在两处明显的疏漏: sendRequest()的返回值括号未闭合,实际定义应为Single<Option<BeResponse>>BeResponse类存在拼写错误,原代码误写为BeReponse
实现最大3次重试的落地方案
因为你的“请求失败”是体现在返回的BeResponse.error字段非空,不是RxJava流程触发onError事件,所以RxJava原生的retry()系列操作符无法直接适用,必须通过手动判断返回值、在递归调用链路里传递重试计数的方式实现次数限制,具体操作步骤:
- 抽离实际发起网络请求的基础逻辑,不混入重试分支
- 封装带重试计数参数的递归请求方法,当计数达到3次上限时,直接返回错误结果,不再发起新请求
- 把错误判断、重试触发、结果返回的逻辑和Option的映射逻辑解耦,避免类型不匹配的问题
代码实现如下:
// 最大允许重试次数 const val MAX_RETRY_TIMES = 3 // 实际发起网络请求的基础逻辑,无重试逻辑 private fun sendRequestCore(): Single<Option<BeResponse>> { // 原有将Either<ApiError, Data>转换为BeResponse、再封装为Option的原逻辑 } /** * 带次数限制的请求方法 * @param currentRetryCount 当前已经重试的次数,默认0代表首次请求 */ fun sendRequestWithLimit(currentRetryCount: Int = 0): Single<Option<BeResponse>> { return sendRequestCore() .flatMap { currentOption -> currentOption.fold( // Option为空时直接返回空结果 ifEmpty = { Single.just(None) }, ifSome = { beResponse -> // 判断是否命中业务错误 if (beResponse.error != null) { // 达到最大重试次数,直接返回错误结果终止流程 if (currentRetryCount >= MAX_RETRY_TIMES) { Single.just(Some(beResponse)) } else { // 未达次数上限,重试次数+1,发起下一次请求 sendRequestWithLimit(currentRetryCount + 1) } } else { // 请求成功,直接返回有效数据 Single.just(Some(beResponse)) } } ) } }
逻辑校验说明
上述实现不会出现无限循环的原因:
- 首次请求触发后,每一次重试都会携带累计的重试计数,不存在无状态递归
- 当连续失败达到3次后,代码会直接把带错误的BeResponse结果返回给下游,不会再触发新的网络请求
- 成功拿到有效数据后会直接终止流程,不会进入重试分支
可调整的优化方向
- 可以在重试分支增加固定/指数退避延迟,避免短时间内高频请求后端
- 不需要通过
null.toOption()构造空Option,直接使用Arrow的None单例即可规避空指针风险 - 可以把业务错误的判断逻辑抽成独立的函数,方便后续调整重试触发的规则
内容的提问来源于stack exchange,提问作者Ivan Sakharovskii
相关产品推荐
相关产品推荐

