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

RxJava2重试逻辑定制:如何实现仅404或非404响应时的重试控制?

嘿,针对你这两个关于RxJava2结合Retrofit的重试逻辑问题,我来给你详细拆解解决方案~

问题1:仅当响应为404时执行重试

要实现只有404响应才触发重试,核心是用retryWhen操作符(代替无条件的retry(n)),它允许我们自定义重试的触发条件。这里分两种常见场景处理:

场景1:你的Retrofit接口返回Response<T>(可直接获取响应码)

这种情况下,我们可以先在map操作里判断响应码,404时抛出特定异常,再在retryWhen里捕获该异常触发重试:

// 先定义一个自定义异常,用来标记404情况
class Http404Exception extends Exception {}

// 修改后的请求链
new RequestFactory()
    .requestBuilder
    .create(Service.class)
    .getData(id)
    .map(response -> {
        if (response.code() == 404) {
            // 404时抛出自定义异常,供retryWhen识别
            throw new Http404Exception();
        }
        // 非404的成功响应,返回目标数据
        return response.object;
    })
    .doOnError(t -> Log.e(NET, "Error fetching data id '" + id + "': " + t))
    .retryWhen(errors -> errors.flatMap(error -> {
        // 仅当捕获到404异常时,触发最多3次重试
        if (error instanceof Http404Exception) {
            return Observable.range(1, 3);
        }
        // 其他异常直接传递,不触发重试
        return Observable.error(error);
    }))
    .onErrorResumeNext(Observable.empty())
    .subscribeOn(Schedulers.io())

场景2:接口直接返回实体类(Retrofit自动将非2xx响应转为HttpException)

这种情况下,无需自定义异常,直接在retryWhen里判断HttpException的响应码即可:

new RequestFactory()
    .requestBuilder
    .create(Service.class)
    .getData(id)
    .map(response -> response.object)
    .doOnError(t -> Log.e(NET, "Error fetching data id '" + id + "': " + t))
    .retryWhen(errors -> errors.flatMap(error -> {
        // 检查是否是404的Http异常,是则触发最多3次重试
        if (error instanceof HttpException && ((HttpException) error).code() == 404) {
            return Observable.range(1, 3);
        }
        // 其他异常终止重试,传递错误
        return Observable.error(error);
    }))
    .onErrorResumeNext(Observable.empty())
    .subscribeOn(Schedulers.io())
问题2:仅当响应码非404时重试(404无需重试)

这个需求是问题1的反向逻辑,同样用retryWhen来控制重试开关,以下是对应修改方案:

场景1:接口返回Response<T>

class Http404Exception extends Exception {}

new RequestFactory()
    .requestBuilder
    .create(Service.class)
    .getData(id)
    .map(response -> {
        if (response.code() == 404) {
            // 404直接抛出异常,后续不重试
            throw new Http404Exception();
        } else if (!response.isSuccessful()) {
            // 其他非成功响应,抛出通用Http异常触发重试
            throw new HttpException(response);
        }
        return response.object;
    })
    .doOnError(t -> Log.e(NET, "Error fetching data id '" + id + "': " + t))
    .retryWhen(errors -> errors.flatMap(error -> {
        // 遇到404异常,直接终止重试传递错误
        if (error instanceof Http404Exception) {
            return Observable.error(error);
        }
        // 其他异常,触发最多3次重试
        return Observable.range(1, 3);
    }))
    .onErrorResumeNext(Observable.empty())
    .subscribeOn(Schedulers.io())

场景2:接口直接返回实体类

new RequestFactory()
    .requestBuilder
    .create(Service.class)
    .getData(id)
    .map(response -> response.object)
    .doOnError(t -> Log.e(NET, "Error fetching data id '" + id + "': " + t))
    .retryWhen(errors -> errors.flatMap(error -> {
        // 若是404异常,不重试直接传递错误
        if (error instanceof HttpException && ((HttpException) error).code() == 404) {
            return Observable.error(error);
        }
        // 其他异常,最多重试3次
        return Observable.range(1, 3);
    }))
    .onErrorResumeNext(Observable.empty())
    .subscribeOn(Schedulers.io())

补充说明

retryWhen的核心逻辑是:当上游抛出错误时,它会接收该错误并返回一个Observable。如果返回的Observable发射数据,就会触发上游重试;如果返回的是Observable.error(),则会终止整个流并传递错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:37:21