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

如何用RxJava2的repeatWhen实现Retrofit2请求的条件重试

解决RxJava2中空响应延迟重试的问题

我来帮你搞定这个需求!针对服务器返回空响应(null或者空List)时延迟5秒重试的场景,咱们可以结合RxJava的retryWhen操作符和自定义校验逻辑来实现,具体步骤如下:

1. 定义自定义异常标记空响应

先创建一个专属异常,用来区分“空响应”和其他类型的错误(比如网络超时、服务器5xx错误),这样后续重试逻辑能精准识别触发条件:

class EmptyResponseException extends Exception {
    public EmptyResponseException() {
        super("Received empty response from server");
    }
}

2. 校验响应并抛出空响应异常

在Retrofit请求之后,添加flatMap操作检查返回的List状态:如果是null或者空列表,就抛出我们定义的EmptyResponseException,让重试逻辑能捕获到这个信号:

RetrofitFactory.getRetrofitService().getWidgets(mDataManager.getBidId())
    .subscribeOn(Schedulers.io())
    // 校验响应是否为空,为空则抛出异常
    .flatMap(widgets -> {
        if (widgets == null || widgets.isEmpty()) {
            return Single.error(new EmptyResponseException());
        }
        return Single.just(widgets);
    })

3. 用retryWhen实现延迟重试

通过retryWhen监听错误流,当捕获到EmptyResponseException时,用Observable.timer实现5秒延迟后触发重试;如果是其他异常,则直接传递错误终止流程:

.retryWhen(throwables -> throwables.flatMap(throwable -> {
        // 仅对空响应异常执行重试
        if (throwable instanceof EmptyResponseException) {
            // 延迟5秒后发出重试信号
            return Observable.timer(5, TimeUnit.SECONDS);
        }
        // 其他异常直接抛出,不再重试
        return Observable.error(throwable);
    }))
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
        validWidgets -> {
            // 处理正常的非空响应数据
        },
        finalError -> {
            // 处理最终错误(比如重试后依然空、网络彻底失败等)
        }
    );

可选:限制最大重试次数

如果不想无限重试,可给逻辑加次数限制。比如最多重试3次,用zip结合Observable.range实现计数器:

.retryWhen(throwables -> throwables
    .zipWith(Observable.range(1, 3), (throwable, retryCount) -> {
        if (throwable instanceof EmptyResponseException && retryCount <= 3) {
            return retryCount;
        }
        // 超过重试次数或非空响应异常,直接抛出错误
        throw new RuntimeException(throwable);
    })
    .flatMap(retryCount -> Observable.timer(5, TimeUnit.SECONDS))
)

注意点

  • 如果你的Retrofit在服务器返回空响应体时会直接抛出HttpException(比如未配置Converter处理空响应),需要先在onErrorResumeNext里解析响应体是否为空,再转换为EmptyResponseException。
  • 重试的延迟逻辑在IO线程执行,不会阻塞主线程,符合RxJava的线程调度规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:02:57