RxJava中repeat操作符源码分析

1,109 阅读4分钟

一、示例

    Observable.just("hello repeat")
        .repeat(3)
        .subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                System.out.println(s);
                    }
        });

二、repeat作用

repeat是用于发射特定数据重复多次的Observable的一种方式。 repeat会重复地发射数据。某些实现允许我们重复某个数据序列,还有一些允许我们限制重复的次数。

repeat不是创建一个Observable,而是重复发射原始Observable的数据序列,这个序列或者是无线,或者是通过repeat(n)指定的重复次数。

三、底层源码分析

  1. Observable调用其方法repeat(n),会先对n进行检测: 若times小于0,则抛出异常; 若等于0,则执行empty() 最后则是执行RxJavaPlugins.onAssembly(new ObservableRepeat<T>(this, times))
public final Observable<T> repeat(long times) {
        if (times < 0) {
            throw new IllegalArgumentException("times >= 0 required but it was " + times);
        }
        if (times == 0) {
            return empty();
        }
        return RxJavaPlugins.onAssembly(new ObservableRepeat<T>(this, times));
    }

在将该方法之前,先讲解其中的类ObservableRepeat类 该类是用于实现repeat操作符的核心。

  1. new ObservableRepeat<T>(this, times)创建 将Observable赋值给source,而count则是赋值给成员变量count

该类中同样也有subscribeActual这个重要的方法:

    @Override
    public void subscribeActual(Observer<? super T> s) {
        SequentialDisposable sd = new SequentialDisposable();
        s.onSubscribe(sd);

        RepeatObserver<T> rs = new RepeatObserver<T>(s, count != Long.MAX_VALUE ? count - 1 : Long.MAX_VALUE, sd, source);
        rs.subscribeNext();
    }

注意这儿有静态内部类:RepeatObserver,该类是实现Observer接口,并继承AtomicInteger父类,以保证数据原子性。

    RepeatObserver(Observer<? super T> actual, long count, SequentialDisposable sd, ObservableSource<? extends T> source) {
            this.actual = actual;
            this.sd = sd;
            this.source = source;
            this.remaining = count;
        }

该类初始化时会将count赋值给其内部,具体的重复发送操作是在该类中完成的。

rs.subscribeNext()方法即为重复发射数据:

    /**
         * Subscribes to the source again via trampolining.
         */
        void subscribeNext() {
            if (getAndIncrement() == 0) {
                int missed = 1;
                for (;;) {
                    if (sd.isDisposed()) {
                        return;
                    }
                    
                    //该方法即为发射发射对应的数据
                    //即原始observable
                    source.subscribe(this);

                    missed = addAndGet(-missed);
                    if (missed == 0) {
                        break;
                    }
                }
            }
        }

在一次数据发送完成后,就会调用onComplete方法,而在RepeatObserver类中重写了onSubscribe()、onNext()、onError()、onComplete()方法, 在onComplete()方法又会将remaining减一,再次执行subscribeNext方法,开次重复输出数据。

        @Override
        public void onComplete() {
            long r = remaining;
            if (r != Long.MAX_VALUE) {
                remaining = r - 1;
            }
            
            //当remaining不为零时,就会再次执行subscurbeNext()
            //否则则执行s,即传入的观察者observer
            if (r != 0L) {
                //核心代码
                subscribeNext();
            } else {
                actual.onComplete();
            }
        }

四、repeat相关的操作符

repeat相关的操作符:repeatWhen和repeatUntil

(一)repeatWhen

repeatWhen不是缓存和重放原始Observable的数据序列,而是有条件地重新订阅和发射原来的Observable。

1.示例

        Observable.range(0, 9).repeatWhen(new Function<Observable<Object>, ObservableSource<?>>() {
            @Override
            public ObservableSource<?> apply(Observable<Object> objectObservable) throws Exception {
                return Observable.timer(10, TimeUnit.SECONDS);
            }
        }).subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                System.out.println(integer);
            }
        });

2.分析

  • 首先Observable.range(0, 9)调用并创建 ObservableRange(start, count)类;
  • 通过repeatWhen(new Function)调用并创建ObservableRepeatWhen(Observable source, Function handler)类
  • 最后调用订阅方法subscribe()进行订阅。

其内部是先运行 ObservableRepeatWhen.subscribeActual方法:

    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        Subject<Object> signaller = PublishSubject.create().toSerialized();

        ObservableSource<?> other;

        try {
            //该方法将会调用reapeatWhen()方法中的new Function类的重写的apply()方法
            other = ObjectHelper.requireNonNull(handler.apply(signaller), "The handler returned a null ObservableSource");
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            EmptyDisposable.error(ex, observer);
            return;
        }

        RepeatWhenObserver<T> parent = new RepeatWhenObserver<T>(observer, signaller, source);
        observer.onSubscribe(parent);

        other.subscribe(parent.inner);

        // 核心代码
        parent.subscribeNext();
    }

之后再调用ObservableRepeatWhen类的内部类RepeatWhenObserver类,并初始化该类

而后再调用parent.subscribeNext()方法 该方法具体如下:

        void subscribeNext() {
            if (wip.getAndIncrement() == 0) {

                do {
                    if (isDisposed()) {
                        return;
                    }

                    if (!active) {
                        //注意第二次active的值会在onComplete方法中重新赋值为false
                        active = true;
                        
                        //看该行代码
                        source.subscribe(this);
                    }
                } while (wip.decrementAndGet() != 0);
            }
        }

source.subscribe(this)会调用Observable类的subscribe()方法: 该方法的又调用subscribeActual(observer),就会调用ObservableRange类的subscribeActual()方法:

    @Override
    protected void subscribeActual(Observer<? super Integer> o) {
        RangeDisposable parent = new RangeDisposable(o, start, end);
        
        // 调用ObservableRepeatWhen类的onSubscribe()方法
        o.onSubscribe(parent);
        
        //核心代码,输出的数据
        parent.run();
    }

其中RangeDisposable为ObservableRange的内部类

而后再调用

        void run() {
            if (fused) {
                return;
            }
            Observer<? super Integer> actual = this.actual;
            long e = end;
            for (long i = index; i != e && get() == 0; i++) {
                // 调用在主类中自定义的onNext()方法
                // 即subscribe(new Consumer<Integer>() {})方法
                actual.onNext((int)i);
            }
            if (get() == 0) {
                lazySet(1);
                actual.onComplete();
            }
        }

从而实现第一次完成onNext()方法的订阅后,在actual.onComplete();中会实现第二次的调用:

        @Override
        public void onComplete() {
            active = false;
            signaller.onNext(0);
        }

此时就会使用到PublicSubject类实现第二次的延迟输出: (signaller = PublishSubject.create().toSerialized();)

在延迟10s后会再次调用ObservableRepeatWhen类中的subscribeNext()方法,进行第二次的发射数据,再次不再累赘。