Android中Retrofit+RxJava请求onNext未触发但onComplete已执行问题求助
用RxJava给Retrofit请求添加智能重试方案
嘿,我刚好处理过类似的Android场景,结合RxJava可以轻松解决你这种WiFi连接后请求偶尔失败的问题,给你几个实用的方案:
1. 基础固定次数重试
如果只是想简单地重试指定次数,直接用RxJava的retry()操作符就行,比如重试3次:
yourRetrofitApiService.initRequest() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .retry(3) // 失败后重试3次 .subscribe(new Observer<InitResponse>() { @Override public void onSubscribe(Disposable d) { // 可以保存Disposable用于后续取消请求 } @Override public void onNext(InitResponse response) { // 初始化成功后的业务逻辑 } @Override public void onError(Throwable e) { // 所有重试都失败后的兜底处理 } @Override public void onComplete() {} });
2. 只重试网络相关错误(智能过滤)
很多时候我们不需要重试所有错误,比如服务器返回400这类业务错误就没必要重试。可以用retryWhen()精准判断错误类型,只针对网络连接类失败重试:
yourRetrofitApiService.initRequest() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .retryWhen(throwableFlowable -> throwableFlowable.flatMap(throwable -> { // 判断是否是网络类错误(比如IOException、UnknownHostException等) if (throwable instanceof IOException) { // 延迟1秒后重试,避免频繁请求给网络造成压力 return Observable.timer(1, TimeUnit.SECONDS); } // 非网络错误,直接传递错误终止重试 return Observable.error(throwable); })) .subscribe(/* 订阅逻辑同上 */);
要是想优化体验,还可以改成递增延迟(比如第一次1秒、第二次2秒、第三次4秒),避免短时间内重复请求。
3. 结合WiFi连接状态的重试(更贴合你的场景)
有时候系统显示WiFi连接成功,但实际还没通网,这时候可以在重试前先检查WiFi的实际可用性:
// 先写一个检查WiFi是否可用的工具方法 private Observable<Boolean> isWifiAvailable(Context context) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo wifiInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI); return Observable.just(wifiInfo != null && wifiInfo.isConnected()); } // 整合到重试逻辑中 yourRetrofitApiService.initRequest() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .retryWhen(throwableFlowable -> throwableFlowable.flatMap(throwable -> { if (throwable instanceof IOException) { // 先检查WiFi是否还处于连接状态 return isWifiAvailable(this) .flatMap(isAvailable -> { if (isAvailable) { // WiFi可用,延迟1秒重试 return Observable.timer(1, TimeUnit.SECONDS); } else { // WiFi已断开,终止重试并抛出对应错误 return Observable.error(new Throwable("WiFi已断开连接")); } }); } return Observable.error(throwable); })) .subscribe(/* 订阅逻辑同上 */);
这个方案能避免在WiFi已经断开的情况下做无效重试,更适配你的业务场景。
额外提醒
- 记得在页面销毁时取消订阅,用
CompositeDisposable管理所有Disposable可以避免内存泄漏。 - 如果你的Retrofit用的是RxJava3,把代码里的
Observable换成Flowable或Single即可,操作符用法基本一致。 - 可以给重试逻辑加个最大次数限制,比如在
retryWhen里加入计数器,超过次数就终止重试。
内容的提问来源于stack exchange,提问作者OhWhen
相关产品推荐
相关产品推荐

