/** * Returns an Observable that automatically connects to this ConnectableObservable * when the first Subscriber subscribes. * * @return an Observable that automatically connects to this ConnectableObservable * when the first Subscriber subscribes */ @NonNull public Observable<T> autoConnect() { return autoConnect(1); } /**
/** * Child Observers will observe the events of the ConnectableObservable on the * specified scheduler. * @param <T> the value type * @param co the connectable observable instance * @param scheduler the target scheduler * @return the new ConnectableObservable instance */ public static <T> ConnectableObservable<T> observeOn(final ConnectableObservable<T> co, final Scheduler scheduler) { final Observable<T> observable = co.observeOn(scheduler); return RxJavaObservablePlugins.onAssembly(new Replay<T>(co, observable)); }
/** * Returns a new {@link ObservableSource} that multicasts (shares) the original {@link ObservableSource}. As long as * there is at least one {@link Observer} this {@link ObservableSource} will be subscribed and emitting data. * When all subscribers have disposed it will dispose the source {@link ObservableSource}. * <p> * This is an alias for {@link #publish()}.{@link ConnectableObservable#refCount()}. * <p> * <img width="640" height="510" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/publishRefCount.png" alt=""> * <dl> * <dt><b>Scheduler:</b></dt> * <dd>{@code share} does not operate by default on a particular {@link Scheduler}.</dd> * </dl> * * @return an {@code ObservableSource} that upon connection causes the source {@code ObservableSource} to emit items * to its {@link Observer}s * @see <a href="http://reactivex.io/documentation/operators/refcount.html">ReactiveX operators documentation: RefCount</a> */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) public final Observable<T> share() { return publish().refCount(); }
@Override public void connect(Consumer<? super Disposable> connection) { co.connect(connection); }
@Override public void run() { co.subscribe(to1); } };
@Test public void testObserveOn() { ConnectableObservable<Integer> co = Observable.range(0, 1000).publish(); Observable<Integer> obs = co.observeOn(Schedulers.computation()); for (int i = 0; i < 1000; i++) { for (int j = 1; j < 6; j++) { List<TestObserver<Integer>> tss = new ArrayList<TestObserver<Integer>>(); for (int k = 1; k < j; k++) { TestObserver<Integer> ts = new TestObserver<Integer>(); tss.add(ts); obs.subscribe(ts); } Disposable s = co.connect(); for (TestObserver<Integer> ts : tss) { ts.awaitTerminalEvent(2, TimeUnit.SECONDS); ts.assertTerminated(); ts.assertNoErrors(); assertEquals(1000, ts.valueCount()); } s.dispose(); } } }
@Test public void testTakeUntilWithPublishedStream() { Observable<Integer> xs = Observable.range(0, Observable.bufferSize() * 2); TestObserver<Integer> ts = new TestObserver<Integer>(); ConnectableObservable<Integer> xsp = xs.publish(); xsp.takeUntil(xsp.skipWhile(new Predicate<Integer>() { @Override public boolean test(Integer i) { return i <= 3; } })).subscribe(ts); xsp.connect(); System.out.println(ts.values()); }
@Test public void connectConsumerThrows() { ConnectableObservable<Integer> co = Observable.range(1, 2) .replay(); try { co.connect(new Consumer<Disposable>() { @Override public void accept(Disposable t) throws Exception { throw new TestException(); } }); fail("Should have thrown"); } catch (TestException ex) { // expected } co.test().assertEmpty().cancel(); co.connect(); co.test().assertResult(1, 2); }
@Test public void cancelOnArrival2() { ConnectableObservable<Integer> co = PublishSubject.<Integer>create() .replay(Integer.MAX_VALUE); co.test(); co .autoConnect() .test(true) .assertEmpty(); }
@Override public void run() { co.test(); } };
/** * Returns a new {@link ObservableSource} that multicasts (shares) the original {@link ObservableSource}. As long as * there is at least one {@link Observer} this {@link ObservableSource} will be subscribed and emitting data. * When all subscribers have disposed it will dispose the source {@link ObservableSource}. * <p> * This is an alias for {@link #publish()}.{@link ConnectableObservable#refCount()}. * <p> * <img width="640" height="510" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/publishRefCount.png" alt=""> * <dl> * <dt><b>Scheduler:</b></dt> * <dd>{@code share} does not operate by default on a particular {@link Scheduler}.</dd> * </dl> * * @return an {@code ObservableSource} that upon connection causes the source {@code ObservableSource} to emit items * to its {@link Observer}s * @see <a href="http://reactivex.io/documentation/operators/refcount.html">ReactiveX operators documentation: RefCount</a> */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) public final Observable<T> share() { return publish().refCount(); }
@Override public void connect(Consumer<? super Disposable> connection) { co.connect(connection); }
@Override public void run() { co.subscribe(to1); } };
@Test public void testBackpressureFastSlow() { ConnectableObservable<Integer> is = Observable.range(1, Observable.bufferSize() * 2).publish(); Observable<Integer> fast = is.observeOn(Schedulers.computation()) .doOnComplete(new Action() { @Override Observable<Integer> slow = is.observeOn(Schedulers.computation()).map(new Function<Integer, Integer>() { int c; is.connect(); ts.awaitTerminalEvent(); ts.assertNoErrors();
@Test public void disposeOnArrival() { ConnectableObservable<Integer> co = Observable.<Integer>empty().publish(); co.test(true).assertEmpty(); }
/** * Returns an Observable that automatically connects to this ConnectableObservable * when the first Subscriber subscribes. * * @return an Observable that automatically connects to this ConnectableObservable * when the first Subscriber subscribes */ @NonNull public Observable<T> autoConnect() { return autoConnect(1); } /**
@Test public void replayNoLeak() throws Exception { System.gc(); Thread.sleep(100); long start = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed(); source = Observable.fromCallable(new Callable<Object>() { @Override public Object call() throws Exception { return new byte[100 * 1000 * 1000]; } }) .replay(1) .refCount(); source.subscribe(); System.gc(); Thread.sleep(100); long after = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed(); source = null; assertTrue(String.format("%,3d -> %,3d%n", start, after), start + 20 * 1000 * 1000 > after); }