rxjava+retrofit轮询

本文探讨了使用RxJava和Retrofit进行轮询时遇到的问题,特别是如何处理网络请求失败和限制错误重试次数。通过retryWhen和repeatWhen的结合,配合zipWith函数限制错误次数,但在实践中发现它们无法有效配合。解决方案是改用repeat和delay,确保delay在先,repeat在后,以防止无限循环。示例代码展示了如何实现一个在失败3次后停止,每次失败间隔5秒的轮询方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

rxjava+retrofit是一个非常流行的组合,那些从头说到尾的怎么配置的,怎么用的我就不说了,这些网上太多了,我今天说说轮询的一个小问题吧。

1、本来轮询的话会遇到只要写一个repeatWhen就好了,但事情好像没有这么简单,如果遇到了网络请求的失败的话,repeatWhen是不会调用的,因为repeatWhen是在onComplete的时候才触发,这个时候就要用到retryWhen,这个是在onError的时候触发的,关于retryWhen和repeatWhen的区别点击链接

2、如果你是一直都请求超时的话,如果一直请求下去,也是一个不合理的,那么怎么限制请求的次数呢?这个就要用到zipWith这个函数了,当这个函数运行完之后就会调用onComplete的了

3、基于以上的想法,我的第一个做法是使用retryWhen来应付错误,使用repeatWhen来应付轮询的,配合上zipWith来做一个错误的次数限制

4、问题就出现了,我在不断的重复又重复,zipWith根本就没有限制到错误的次数。

5、这个原因我想了很久,和做了实验,发现retryWhen和repeatWhen在这种情况下是不能配合使用的(如果可以的话,恳求回复告诉作者,修改文章,避免误导他人),这个是因为zipWith的存在,zip限制完了次数之后就会调用onComplete,那么repeatWhen在调用onComplete的时候就会调用,这样的话,是一直循环下去,无法停止的。

解决方法:

把repeatWhen改用repeat和delay来代替,本来repeatWhen里面只是返回一个Observable.delay而已。

在使用repeat和delay的时候也要注意,是delay在先,repeat在后,不然delay是没有效果的,会拼命的repeat,我的猜测是先调用了repeat,delay是repeat之后调用,那么repeat是没有限制时间的,所有就生成了很多的repeat对象,在后面调用delay,但如果是delay先的话,就会先delay再repeat。(个人直觉,如果有人知道的话,请回复,以修改文章

具体代码如下:

ApiManager.getInstance().getService()
                .getNotice(token)
                .compose(RxUtils.<GetNoticeResponse>doAndShowBackgroundTransformer())
                .compose(RxUtils.<GetNoticeResponse>retryTimesAndDelay(3, 5, TimeUnit.SECONDS))

        

效果:一个获取通知的轮询方法如果有错误,会重复调用3次,如果3次都不成功就会停止,每次失败的间隔是5秒钟,如果没有错误的话就一直轮询下去,每次轮询的时间也是5秒钟,和失败是一样的,也可以写成不一样的,这个读者自己修改。

第一个compose就是subscribeOn和observeableOn的设置,我就不写出来

第二个如下:

/**
     * @param times    如果-1,表示无限
     * @param delay
     * @param timeUnit
     * @param <T>
     * @return
     */
    public static <T> ObservableTransformer<T, T> retryTimesAndDelay(final int times, int delay, TimeUnit timeUnit) {
        final int mTimes = times;
        final int mDelay = delay;
        final TimeUnit mTimeUnit = timeUnit;
        return new ObservableTransformer<T, T>() {
            @Override
            public ObservableSource<T> apply(Observable<T> upstream) {
                return upstream
                        .delay(mDelay, mTimeUnit)
                        .repeatUntil(new BooleanSupplier() {
                            @Override
                            public boolean getAsBoolean() throws Exception {
                                return stopRepeat;
                            }
                        }).retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() {
                            @Override
                            public ObservableSource<?> apply(Observable<Throwable> throwableObservable) throws Exception {

                                if (mTimes != -1)
                                    throwableObservable = throwableObservable.zipWith(Observable.range(1, mTimes), new BiFunction<Throwable, Integer, Throwable>() {
                                        @Override
                                        public Throwable apply(Throwable throwable, Integer integer) throws Exception {
                                            LogUtils.i("abc", "重试的次数" + integer);
                                            LogUtils.e(throwable);
                                            stopRepeat = integer == times;
                                            return throwable;
                                        }
                                    });
                                return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() {
                                    @Override
                                    public ObservableSource<?> apply(Throwable throwable) throws Exception {
                                        if (throwable instanceof NoNetworkException ||
                                                throwable instanceof NoTokenException ||
                                                throwable instanceof HttpResponseException) {
                                            return Observable.error(throwable);
                                        } else
                                            return Observable.timer(mDelay, mTimeUnit);
                                    }
                                });

                            }
                        });
            }
        };
    }

里面有些日志类,是别的类库,这个就不要理会了,看主要的架构,留意zipWith和flatMap,flatMap是用来获取错误,自己可以在里面写内容处理错误。

 

这段代码我也是研究了很久,参考了很多网址。如果有任务纰漏,请回复,感谢大神的指教

(本人对rxjava的理解不是很透切,这里的理解很有可能是错误的。请回复或者发邮件到tvvbbb@163.com联系本人)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值