/** * 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(); }
/** * 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(); }
@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); }
@Test public void publishNoLeak() 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 { throw new ExceptionData(new byte[100 * 1000 * 1000]); } }) .publish() .refCount(); source.subscribe(Functions.emptyConsumer(), Functions.emptyConsumer()); 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); }
@Test public void testAlreadyUnsubscribedClient() { Observer<Integer> done = DisposingObserver.INSTANCE; Observer<Integer> o = TestHelper.mockObserver(); Observable<Integer> result = Observable.just(1).publish().refCount(); result.subscribe(done); result.subscribe(o); verify(o).onNext(1); verify(o).onComplete(); verify(o, never()).onError(any(Throwable.class)); }
@Test public void publishNoLeak2() 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]; } }).concatWith(Observable.never()) .publish() .refCount(); Disposable s1 = source.test(); Disposable s2 = source.test(); s1.dispose(); s2.dispose(); s1 = null; s2 = null; 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); }
@Test public void replayNoLeak2() 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]; } }).concatWith(Observable.never()) .replay(1) .refCount(); Disposable s1 = source.subscribe(); Disposable s2 = source.subscribe(); s1.dispose(); s2.dispose(); s1 = null; s2 = null; 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); }
countBefore.incrementAndGet(); }).publish().refCount() .doOnSubscribe(new Consumer<Disposable>() { @Override
@Test public void testRefCountSynchronousTake() { final AtomicInteger nextCount = new AtomicInteger(); Observable<Integer> r = Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9) .doOnNext(new Consumer<Integer>() { @Override public void accept(Integer l) { System.out.println("onNext --------> " + l); nextCount.incrementAndGet(); } }) .take(4) .publish().refCount(); final AtomicInteger receivedCount = new AtomicInteger(); r.subscribe(new Consumer<Integer>() { @Override public void accept(Integer l) { receivedCount.incrementAndGet(); } }); System.out.println("onNext: " + nextCount.get()); assertEquals(4, receivedCount.get()); assertEquals(4, receivedCount.get()); }
@Test public void disposed() { TestHelper.checkDisposed(Observable.just(1).publish().refCount()); }
o.publish().refCount().subscribeOn(Schedulers.newThread()).subscribe(s); System.out.println("send unsubscribe");
@Test public void testAlreadyUnsubscribedInterleavesWithClient() { ReplaySubject<Integer> source = ReplaySubject.create(); Observer<Integer> done = DisposingObserver.INSTANCE; Observer<Integer> o = TestHelper.mockObserver(); InOrder inOrder = inOrder(o); Observable<Integer> result = source.publish().refCount(); result.subscribe(o); source.onNext(1); result.subscribe(done); source.onNext(2); source.onComplete(); inOrder.verify(o).onNext(1); inOrder.verify(o).onNext(2); inOrder.verify(o).onComplete(); verify(o, never()).onError(any(Throwable.class)); }
.publish().refCount();
.publish().refCount();
o.publish().refCount().subscribeOn(Schedulers.computation()).subscribe(s); System.out.println("send unsubscribe");
.publish().refCount();
@Test public void onlyFirstShouldSubscribeAndLastUnsubscribe() { final AtomicInteger subscriptionCount = new AtomicInteger(); final AtomicInteger unsubscriptionCount = new AtomicInteger(); Observable<Integer> o = Observable.unsafeCreate(new ObservableSource<Integer>() { @Override public void subscribe(Observer<? super Integer> observer) { subscriptionCount.incrementAndGet(); observer.onSubscribe(Disposables.fromRunnable(new Runnable() { @Override public void run() { unsubscriptionCount.incrementAndGet(); } })); } }); Observable<Integer> refCounted = o.publish().refCount(); Disposable first = refCounted.subscribe(); assertEquals(1, subscriptionCount.get()); Disposable second = refCounted.subscribe(); assertEquals(1, subscriptionCount.get()); first.dispose(); assertEquals(0, unsubscriptionCount.get()); second.dispose(); assertEquals(1, unsubscriptionCount.get()); }
@Test public void testRefCount() { TestScheduler s = new TestScheduler(); Observable<Long> interval = Observable.interval(100, TimeUnit.MILLISECONDS, s).publish().refCount();
@Test public void testConnectDisconnectConnectAndSubjectState() { Observable<Integer> o1 = Observable.just(10); Observable<Integer> o2 = Observable.just(20); Observable<Integer> combined = Observable.combineLatest(o1, o2, new BiFunction<Integer, Integer, Integer>() { @Override public Integer apply(Integer t1, Integer t2) { return t1 + t2; } }) .publish().refCount(); TestObserver<Integer> ts1 = new TestObserver<Integer>(); TestObserver<Integer> ts2 = new TestObserver<Integer>(); combined.subscribe(ts1); combined.subscribe(ts2); ts1.assertTerminated(); ts1.assertNoErrors(); ts1.assertValue(30); ts2.assertTerminated(); ts2.assertNoErrors(); ts2.assertValue(30); }