定期收集Observable的数据放进一个数据包裹,然后发射这些数据包裹,而不是一次发射一 个值。
我们分析一下buffer函数
new了一个OperatorBufferWithSize
这里的parent是OnSubscribeRange,operator是OperatorBufferWithSize,这里调用OnSubscribeRange的call
Buffer
操作符将一个Observable变换为另一个,原来的Observable正常发射数据,变换产生 的Observable发射这些数据的缓存集合。Buffer
操作符在很多语言特定的实现中有很多种变 体,它们在如何缓存这个问题上存在区别。
注意:如果原来的Observable发射了一个 onError通知,
Buffer会立即传递这个通知,而不 是首先发射缓存的数据,即使在这之前缓存中包含了原始Observable发射的数据。
Window
操作符与 Buffer
类似,但是它在发射之前把收集到的数据放进单独的Observable, 而不是放进一个数据结构
demo
final Observer<List<Integer>> observer = new Observer<List<Integer>>() {
@Override
public void onNext(List<Integer> number) {
System.out.println("onNext() ------>>>> " + number);
}
@Override
public void onCompleted() {
System.out.println("Complete!");
}
@Override
public void onError(Throwable e) {
System.out.println("onError!");
}
};
Observable.range(1, 10).buffer(3).subscribe(observer);
输出
onNext() ------>>>> [1, 2, 3]
onNext() ------>>>> [4, 5, 6]
onNext() ------>>>> [7, 8, 9]
onNext() ------>>>> [10]
Complete!
我们分析一下buffer函数
public final Observable<List<T>> buffer(int count) {
return buffer(count, count);
}
public final Observable<List<T>> buffer(int count, int skip) {
return lift(new OperatorBufferWithSize<T>(count, skip));
}
new了一个OperatorBufferWithSize
有前面分析可只,subscribe最终会调用到OnSubscribeLift的call函数
@Override
public void call(Subscriber<? super R> o) {
try {
Subscriber<? super T> st = RxJavaHooks.onObservableLift(operator).call(o);
try {
// new Subscriber created and being subscribed with so 'onStart' it
st.onStart();
parent.call(st);
} catch (Throwable e) {
// localized capture of errors rather than it skipping all operators
// and ending up in the try/catch of the subscribe method which then
// prevents onErrorResumeNext and other similar approaches to error handling
Exceptions.throwIfFatal(e);
st.onError(e);
}
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
// if the lift function failed all we can do is pass the error to the final Subscriber
// as we don't have the operator available to us
o.onError(e);
}
}
st是OperatorBufferWithSize的call返回结果
@Override
public Subscriber<? super T> call(final Subscriber<? super List<T>> child) {
if (skip == count) {
BufferExact<T> parent = new BufferExact<T>(child, count);
child.add(parent);
child.setProducer(parent.createProducer());
return parent;
}
if (skip > count) {
BufferSkip<T> parent = new BufferSkip<T>(child, count, skip);
child.add(parent);
child.setProducer(parent.createProducer());
return parent;
}
BufferOverlap<T> parent = new BufferOverlap<T>(child, count, skip);
child.add(parent);
child.setProducer(parent.createProducer());
return parent;
}
skip=count,返回的是BufferExact这里的parent是OnSubscribeRange,operator是OperatorBufferWithSize,这里调用OnSubscribeRange的call
public void call(final Subscriber<? super Integer> childSubscriber) {
childSubscriber.setProducer(new RangeProducer(childSubscriber, startIndex, endIndex));
}
最终调用stRangeProducer的request方法
public void request(long requestedAmount) {
if (get() == Long.MAX_VALUE) {
// already started with fast-path
return;
}
if (requestedAmount == Long.MAX_VALUE && compareAndSet(0L, Long.MAX_VALUE)) {
// fast-path without backpressure
fastPath();
} else if (requestedAmount > 0L) {
long c = BackpressureUtils.getAndAddRequest(this, requestedAmount);
if (c == 0L) {
// backpressure is requested
slowPath(requestedAmount);
}
}
}
调用addToRequested设置requested
走fastPath分支
void fastPath() {
final long endIndex = this.endOfRange + 1L;
final Subscriber<? super Integer> childSubscriber = this.childSubscriber;
for (long index = currentIndex; index != endIndex; index++) {
if (childSubscriber.isUnsubscribed()) {
return;
}
childSubscriber.onNext((int) index);
}
if (!childSubscriber.isUnsubscribed()) {
childSubscriber.onCompleted();
}
}
for循环调用
childSubscriber.onNext((int) index);
这里childSubscriber为BufferExact
public void onNext(T t) {
List<T> b = buffer;
if (b == null) {
b = new ArrayList<T>(count);
buffer = b;
}
b.add(t);
if (b.size() == count) {
buffer = null;
actual.onNext(b);
}
}
把当前数据添加到buffer,判断buffer中的数量是否达到count,没有则直接返回,达到则调用onNext传递当前的缓存值
我们看一下onNext
actual的onNext最终调用到我们demo中
@Override
public void onNext(List<Integer> number) {
System.out.println("onNext() ------>>>> " + number);
}