Rxjava(变换类)-Window

定期将来自原始Observable的数据分解为一个Observable窗口,发射这些窗口,而不是每次 发射一项数据

Window Buffer 类似,但不是发射来自原始Observable的数据包,它发射的是 Observables,这些Observables中的每一个都发射原始Observable数据的一个子集,最后发 射一个 onCompleted 通知。


demo

        Observable.range(1, 10).window(3).subscribe(new Action1<Observable<Integer>>() {
            @Override
            public void call(final Observable<Integer> obser) {
                obser.subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        System.out.println(integer + " of window " + obser);
                    }
                });
            }
        });
主要看下window的实现

 public final Observable<Observable<T>> window(int count) {
        return window(count, count);
    }
public final Observable<Observable<T>> window(int count, int skip) {
        if (count <= 0) {
            throw new IllegalArgumentException("count > 0 required but it was " + count);
        }
        if (skip <= 0) {
            throw new IllegalArgumentException("skip > 0 required but it was " + skip);
        }
        return lift(new OperatorWindowWithSize<T>(count, skip));
    }

创建了一个OperatorWindowWithSize,当我们subscribe的时候会调用他的call

public Subscriber<? super T> call(Subscriber<? super Observable<T>> child) {
        if (skip == size) {
            WindowExact<T> parent = new WindowExact<T>(child, size);

            child.add(parent.cancel);
            child.setProducer(parent.createProducer());

            return parent;
        } else
        if (skip > size) {
            WindowSkip<T> parent = new WindowSkip<T>(child, size, skip);

            child.add(parent.cancel);
            child.setProducer(parent.createProducer());

            return parent;
        }

        WindowOverlap<T> parent = new WindowOverlap<T>(child, size, skip);

        child.add(parent.cancel);
        child.setProducer(parent.createProducer());

        return parent;

    }

这里skip==size,创建一个WindowExact

public WindowExact(Subscriber<? super Observable<T>> actual, int size) {
            this.actual = actual;
            this.size = size;
            this.wip = new AtomicInteger(1);
            this.cancel = Subscriptions.create(this);
            this.add(cancel);
            this.request(0);
        }

requested设置为了0

同样是OnSubscribeRange,最终调用到RangeProducer的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();
            }
        }

这里的childSubscriber换成了是WindowExact

调用它的onNext

public void onNext(T t) {
            int i = index;

            Subject<T, T> w = window;
            if (i == 0) {
                wip.getAndIncrement();

                w = UnicastSubject.create(size, this);
                window = w;

                actual.onNext(w);
            }
            i++;

            w.onNext(t);

            if (i == size) {
                index = 0;
                window = null;
                w.onCompleted();
            } else {
                index = i;
            }
        }
index为0,创建一个UnicastSubject,size是3

actual.onNext(w);
zh这里最终会调用到我们demo中的onNext,而在onNext中我们又为这个Observable做了一次订阅

然后调用 w.onNext(t);查看是否有这个窗口的订阅者,demo中我们在前面有为这个窗口添加订阅者。

   public void onNext(T t) {
        state.onNext(t);
    }
 public void onNext(T t) {
            if (!done) {
                if (!caughtUp) {
                    boolean stillReplay = false;
                    /*
                     * We need to offer while holding the lock because
                     * we have to atomically switch caughtUp to true
                     * that can only happen if there isn't any concurrent
                     * offer() happening while the emission is in replayLoop().
                     */
                    synchronized (this) {
                        if (!caughtUp) {
                            queue.offer(NotificationLite.next(t));
                            stillReplay = true;
                        }
                    }
                    if (stillReplay) {
                        replay();
                        return;
                    }
                }
                Subscriber<? super T> s = subscriber.get();
                try {
                    s.onNext(t);
                } catch (Throwable ex) {
                    Exceptions.throwOrReport(ex, s, t);
                }
            }
        }

这里由于在demo中我们再次进行了subscribe,最终会设置caughtUp为true,并且设置subscriber,这里会调用到它的onNext,最终调用到我们demo中第二个subscribe中的onNext

回到WindowExact的onNext,如果i值达到size,则置空window和index,调用window的onComplete,这样下次进来的时候会重新创建一个Window



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值