如何用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
相关产品推荐
相关产品推荐

