一、示例
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)指定的重复次数。
三、底层源码分析
- 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操作符的核心。
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()方法,进行第二次的发射数据,再次不再累赘。