Rxjava(变换类)-Buffer

本文介绍了RxJava中的Buffer操作符,它将Observable转换,缓存数据并以集合形式发射。当源Observable发送错误通知时,Buffer会立即传递错误,而不是先发射缓存的数据。此外,还提到了Window操作符的相似性和区别。通过一个demo演示了Buffer的实际使用过程。

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

定期收集Observable的数据放进一个数据包裹,然后发射这些数据包裹,而不是一次发射一 个值。

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);
            }







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值