Rxjava(变换类)-Window

来源:互联网 发布:我要复仇知乎 编辑:程序博客网 时间:2024/06/07 12:39
定期将来自原始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



0 0
原创粉丝点击