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

