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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:05:48