rx.subjects.BehaviorSubject Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rxjava-core Show documentation
Show all versions of rxjava-core Show documentation
rxjava-core developed by Netflix
/**
* Copyright 2014 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package rx.subjects;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicReference;
import rx.Notification;
import rx.Observer;
import rx.functions.Action1;
import rx.subjects.SubjectSubscriptionManager.SubjectObserver;
/**
* Subject that publishes the most recent and all subsequent events to each subscribed {@link Observer}.
*
*
*
* Example usage:
*
*
{@code
* / observer will receive all events.
BehaviorSubject
*
* @param
*/
public final class BehaviorSubject extends Subject {
/**
* Creates a {@link BehaviorSubject} which publishes the last and all subsequent events to each
* {@link Observer} that subscribes to it.
*
* @param defaultValue
* the value which will be published to any {@link Observer} as long as the
* {@link BehaviorSubject} has not yet received any events
* @return the constructed {@link BehaviorSubject}
* @deprecated use {@link #create(T)} instead
*/
public static BehaviorSubject createWithDefaultValue(T defaultValue) {
return create(defaultValue);
}
/**
* Creates a {@link BehaviorSubject} which publishes the last and all subsequent events to each
* {@link Observer} that subscribes to it.
*
* @param defaultValue
* the value which will be published to any {@link Observer} as long as the
* {@link BehaviorSubject} has not yet received any events
* @return the constructed {@link BehaviorSubject}
*/
public static BehaviorSubject create(T defaultValue) {
final SubjectSubscriptionManager subscriptionManager = new SubjectSubscriptionManager();
// set a default value so subscriptions will immediately receive this until a new notification is received
final AtomicReference> lastNotification = new AtomicReference>(new Notification(defaultValue));
OnSubscribe onSubscribe = subscriptionManager.getOnSubscribeFunc(
/**
* This function executes at beginning of subscription.
*
* This will always run, even if Subject is in terminal state.
*/
new Action1>() {
@Override
public void call(SubjectObserver super T> o) {
/*
* When we subscribe we always emit the latest value to the observer.
*
* Here we only emit if it's an onNext as terminal states are handled in the next function.
*/
Notification n = lastNotification.get();
if (n.isOnNext()) {
n.accept(o);
}
}
},
/**
* This function executes if the Subject is terminated before subscription occurs.
*/
new Action1>() {
@Override
public void call(SubjectObserver super T> o) {
/*
* If we are already terminated, or termination happens while trying to subscribe
* this will be invoked and we emit whatever the last terminal value was.
*/
lastNotification.get().accept(o);
}
}, null);
return new BehaviorSubject(onSubscribe, subscriptionManager, lastNotification);
}
private final SubjectSubscriptionManager subscriptionManager;
final AtomicReference> lastNotification;
protected BehaviorSubject(OnSubscribe onSubscribe, SubjectSubscriptionManager subscriptionManager, AtomicReference> lastNotification) {
super(onSubscribe);
this.subscriptionManager = subscriptionManager;
this.lastNotification = lastNotification;
}
@Override
public void onCompleted() {
subscriptionManager.terminate(new Action1>>() {
@Override
public void call(Collection> observers) {
lastNotification.set(new Notification());
for (Observer super T> o : observers) {
o.onCompleted();
}
}
});
}
@Override
public void onError(final Throwable e) {
subscriptionManager.terminate(new Action1>>() {
@Override
public void call(Collection> observers) {
lastNotification.set(new Notification(e));
for (Observer super T> o : observers) {
o.onError(e);
}
}
});
}
@Override
public void onNext(T v) {
// do not overwrite a terminal notification
// so new subscribers can get them
if (lastNotification.get().isOnNext()) {
lastNotification.set(new Notification(v));
for (Observer super T> o : subscriptionManager.rawSnapshot()) {
o.onNext(v);
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy