@Test public void shouldRedeliverSameResultsToDifferentSubscriber() { // Use case: When rotating an activity, ObservableManager will re-subscribe original request's // Observable to a new Observer, which is a member of the new activity instance. In this // case, we may want to redeliver any previous results (if the request is still being // managed by ObservableManager). TestObserver<String> observer = new TestObserver<>(); ReplaySubject<String> subject = ReplaySubject.create(); SubscriptionProxy<String> proxy = SubscriptionProxy.create(subject); proxy.subscribe(observer); subject.onNext("Avanti!"); subject.onCompleted(); proxy.unsubscribe(); TestObserver<String> newSubscriber = new TestObserver<>(); proxy.subscribe(newSubscriber); newSubscriber.awaitTerminalEvent(3, TimeUnit.SECONDS); newSubscriber.assertCompleted(); newSubscriber.assertValue("Avanti!"); observer.assertCompleted(); observer.assertValue("Avanti!"); }
@Override public Observable<RibbonResponse<Observable<T>>> observe() { RibbonHystrixObservableCommand<T> hystrixCommand = request.createHystrixCommand(); ReplaySubject<T> subject = ReplaySubject.create(); hystrixCommand.getObservable().subscribe(subject); return convertToRibbonResponse(subject, hystrixCommand); }
@Test public void shouldKeepDeliveringEventsAfterResubscribed() { TestObserver<String> observer = new TestObserver<>(); ReplaySubject<String> subject = ReplaySubject.create(); SubscriptionProxy<String> proxy = SubscriptionProxy.create(subject); proxy.subscribe(observer); subject.onNext("Avanti 1"); proxy.unsubscribe(); observer = new TestObserver<>(); proxy.subscribe(observer); subject.onNext("Avanti!"); observer.assertValues("Avanti 1", "Avanti!"); }
@Test public void shouldCacheResultsWhileUnsubscribedAndDeliverAfterResubscription() { TestObserver<String> observer = new TestObserver<>(); ReplaySubject<String> subject = ReplaySubject.create(); SubscriptionProxy<String> proxy = SubscriptionProxy.create(subject); proxy.subscribe(observer); proxy.unsubscribe(); observer.assertNoValues(); subject.onNext("Avanti!"); subject.onCompleted(); proxy.subscribe(observer); observer.awaitTerminalEvent(3, TimeUnit.SECONDS); observer.assertValue("Avanti!"); }
@Test public void testUnsubscribeBeforeEmit() { TestObserver<String> observer = new TestObserver<>(); ReplaySubject<String> subject = ReplaySubject.create(); SubscriptionProxy<String> proxy = SubscriptionProxy.create(subject); proxy.subscribe(observer); proxy.unsubscribe(); observer.assertNotCompleted(); observer.assertNoValues(); subject.onNext("Avanti!"); subject.onCompleted(); proxy.subscribe(observer); observer.assertCompleted(); observer.assertValue("Avanti!"); }
@Test public void testAlreadyUnsubscribedInterleavesWithClient() { ReplaySubject<Integer> source = ReplaySubject.create(); Subscriber<Integer> done = Subscribers.empty(); done.unsubscribe(); @SuppressWarnings("unchecked") Observer<Integer> o = mock(Observer.class); InOrder inOrder = inOrder(o); Observable<Integer> result = source.publish().refCount(); result.subscribe(o); source.onNext(1); result.subscribe(done); source.onNext(2); source.onCompleted(); inOrder.verify(o).onNext(1); inOrder.verify(o).onNext(2); inOrder.verify(o).onCompleted(); verify(o, never()).onError(any(Throwable.class)); }
/** Created by Administrator on 2016/3/18. */ public class RxBus { // PublishSubject仅会向Observer释放在订阅之后Observable释放的数据。 private final Subject<Object, Object> publishBus = new SerializedSubject<>(PublishSubject.create()); // AsyncSubject仅释放Observable释放的最后一个数据,并且仅在Observable完成之后。然而如果当Observable因为异常而终止,AsyncSubject将不会释放任何数据,但是会向Observer传递一个异常通知。 private final Subject<Object, Object> asyncBus = new SerializedSubject<>(AsyncSubject.create()); // 当Observer订阅了一个BehaviorSubject,它一开始就会释放Observable最近释放的一个数据对象,当还没有任何数据释放时,它则是一个默认值。接下来就会释放Observable释放的所有数据。 // 如果Observable因异常终止,BehaviorSubject将不会向后续的Observer释放数据,但是会向Observer传递一个异常通知。 private final Subject<Object, Object> behaviorBus = new SerializedSubject<>(BehaviorSubject.create()); // 不管Observer何时订阅ReplaySubject,ReplaySubject会向所有Observer释放Observable释放过的数据。 // 有不同类型的ReplaySubject,它们是用来限定Replay的范围,例如设定Buffer的具体大小,或者设定具体的时间范围。 // 如果使用ReplaySubject作为Observer,注意不要在多个线程中调用onNext、onComplete和onError方法,因为这会导致顺序错乱,这个是违反了Observer规则的。 private final Subject<Object, Object> replayBus = new SerializedSubject<>(ReplaySubject.create()); }
/** Responsible for conducting Bluetooth Low Energy peripheral scans. */ @Singleton public class ScanPresenter extends BasePresenter { static final String LOG_TAG = ScanPresenter.class.getSimpleName(); /** * The peripherals found by the scan peripheral. Initially contains an empty list. * * <p>This subject will emit an empty list if a peripheral scan fails. */ public final ReplaySubject<List<GattPeripheral>> peripherals = ReplaySubject.createWithSize(1); private final BluetoothStack bluetoothStack; private final LoggerFacade logger; private final PeripheralCriteria scanCriteria = new PeripheralCriteria(); private @Nullable Subscription scanSubscription; @Inject public ScanPresenter(@NonNull BluetoothStack bluetoothStack, @NonNull LoggerFacade logger) { this.bluetoothStack = bluetoothStack; this.logger = logger; peripherals.onNext(Collections.<GattPeripheral>emptyList()); } /** * Starts a Bluetooth Low Energy peripheral scan, if one is not already underway. Results are * delivered through the {@link #peripherals} subject. */ public void scan() { if (scanSubscription != null) { return; } final Observable<List<GattPeripheral>> scan = bind(bluetoothStack.discoverPeripherals(scanCriteria)); this.scanSubscription = scan.subscribe( new Subscriber<List<GattPeripheral>>() { @Override public void onCompleted() { ScanPresenter.this.scanSubscription = null; } @Override public void onError(Throwable e) { logger.error(LOG_TAG, "Could not complete scan", e); peripherals.onNext(Collections.<GattPeripheral>emptyList()); ScanPresenter.this.scanSubscription = null; } @Override public void onNext(List<GattPeripheral> gattPeripherals) { logger.info(LOG_TAG, "Scan completed with " + gattPeripherals.size() + " results"); peripherals.onNext(gattPeripherals); } }); } // region Attributes /** Sets the maximum number of peripherals to scan before ending the scan. */ public void setLimit(int limit) { scanCriteria.setLimit(limit); } /** Sets the maximum amount of time that can elapse before a scan is ended. */ public void setDuration(long duration, @NonNull TimeUnit timeUnit) { scanCriteria.setDuration(timeUnit.toMillis(duration)); } // endregion }