- Type Parameters:
-
T- type of the stored value
ReactiveValue. Changes can be observed by using ReactiveTrigger directly or by implementing reactive computation using one of the higher level APIs, for example ReactiveThread.
ReactiveVariable is also used as a bridge between event-driven code and hookless-based code. Event-driven code can instantiate ReactiveVariable<Object> and call set(new Object()) on it whenever it wants to wake up dependent reactive computations.
ReactiveVariable is thus a universal reactive primitive rather than just one kind of reactive data source. It is referenced directly in ReactiveScope and ReactiveTrigger. All other reactive data sources internally use ReactiveVariable either to directly store state or to trigger invalidations.
ReactiveVariable is thread-safe. All methods are safe to call concurrently from multiple threads.
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classReference to particular version ofReactiveVariable. -
Constructor Summary
ConstructorsConstructorDescriptionCreates new instance withnullvalue.ReactiveVariable(ReactiveValue<T> value) Creates new instance holding specifiedReactiveValue.ReactiveVariable(T value) Creates new instance holding specifiedvalue. -
Method Summary
Modifier and TypeMethodDescriptionbooleanequality()Returnstrueif thisReactiveVariableperforms full equality check on assignment.equality(boolean equality) Configures full or reference equality.get()Returns the value held by thisReactiveVariable.inthashCode()Returns identity hash code.Adds strong reference to the specified target object.voidSets current value of thisReactiveVariable.toString()Returns diagnostic string representation of thisReactiveVariable.value()Reads the currentReactiveValuefrom thisReactiveVariableand sets up reactive dependency.voidvalue(ReactiveValue<T> value) Sets currentReactiveValueof thisReactiveVariableand notifies dependent reactive computations.longversion()Returns current version of thisReactiveVariable.
-
Constructor Details
-
ReactiveVariable
Creates new instance holding specifiedReactiveValue.- Parameters:
-
value- initial value of theReactiveVariable - Throws:
-
NullPointerException- ifvalueisnull
-
ReactiveVariable
Creates new instance holding specifiedvalue. TheReactiveValuein the newReactiveVariablewill havefalseReactiveValue.blocking()flag.- Parameters:
-
value- initial value of theReactiveVariable
-
ReactiveVariable
public ReactiveVariable()Creates new instance withnullvalue. The newReactiveVariablewill containReactiveValuewithnullReactiveValue.result().
-
-
Method Details
-
equality
public boolean equality()Returnstrueif thisReactiveVariableperforms full equality check on assignment. This method merely returns what was last passed toequality(boolean). Defaults totrue.- Returns:
-
trueif full equality check is enabled,falseif reference equality is used - See Also:
-
equality
Configures full or reference equality. When thisReactiveVariableis assigned, dependent reactive computations are notified about the change if there is any. In order to check whether the stored value has changed,ReactiveVariablecan either perform full equality check viaReactiveValue.equals(Object)or simple reference equality check viaReactiveValue.same(ReactiveValue). This method can be used to configure which equality test is used. Default is to do full equality check.This method should be called before the
ReactiveVariableis used for the first time.- Parameters:
-
equality-trueto do full equality check,falseto test only reference equality - Returns:
-
this(fluent method) - See Also:
-
version
public long version()Returns current version of thisReactiveVariable. EveryReactiveVariablehas an associated version number, which is incremented after every change. Initial version is 1. Version number does not change if there was no actual change as determined byequality()setting. Reading the version number with this method does not create reactive dependency on theReactiveVariable.- Returns:
-
current version of this
ReactiveVariable - See Also:
-
value
Reads the currentReactiveValuefrom thisReactiveVariableand sets up reactive dependency.This
ReactiveVariableis recorded as a dependency in currentReactiveScope(as identified byReactiveScope.current(). If there is no currentReactiveScope, no dependency is recorded and this method just returns theReactiveValue.ReactiveValue'sReactiveValue.get()is not called, so reactive blocking and exception, if any, are not propagated. They are left encapsulated in the returnedReactiveValue. Callget()if propagation of reactive blocking and exceptions is desirable.- Returns:
-
current
ReactiveValueof thisReactiveVariable, nevernull - See Also:
-
value
Sets currentReactiveValueof thisReactiveVariableand notifies dependent reactive computations. This is the more general version ofset(Object)that allows setting arbitraryReactiveValue.The
valuemay haveReactiveValue.blocking()flag set and it may containReactiveValue.exception(). This is useful in situations whenReactiveVariableis used as a bridge between hookless-based code and event-driven code. The event-driven code may signal that it is not yet ready by setting itsReactiveVariableto a blocking value. It may also communicate exceptions reactively by wrapping them inReactiveValueand storing it inReactiveVariable.If current
ReactiveValueis actually changed as determined byequality()setting,version()is incremented and dependent reactive computations (the ones that accessedvalue()orget()) are notified about the change. If there is no actual change (new value compares equal to the old value perequality()setting), then the state of thisReactiveVariabledoes not change, oldReactiveValueis kept,version()remains the same, and no change notifications are sent.- Parameters:
-
value- newReactiveValueto store in thisReactiveVariable - Throws:
-
NullPointerException- ifvalueisnull - See Also:
-
hashCode
public int hashCode()Returns identity hash code. This implementation is semantically identical toObject.hashCode(). It is just a little faster in order to speed up operations that useReactiveVariableas a key inMap. -
get
Returns the value held by thisReactiveVariable. In most situations, this is the more convenient alternative tovalue(). It is equivalent to callingvalue()and then callingReactiveValue.get()on the returnedReactiveValue.If the stored
ReactiveValuehasReactiveValue.blocking()flag set, reactive blocking is propagated into currentReactiveScopeif there is any. If the storedReactiveValueholds an exception, the exception is propagated wrapped inCompletionException. Otherwise this method just returnsReactiveValue.result().This
ReactiveVariableis recorded as a dependency in currentReactiveScope(as identified byReactiveScope.current()if there is any.- Returns:
-
current value stored in this
ReactiveVariable - Throws:
-
CompletionException- if the storedReactiveValueholds an exception - See Also:
-
set
Sets current value of thisReactiveVariable. In most situations, this is the more convenient alternative tovalue(ReactiveValue). It is equivalent to wrappingvalueinReactiveValueand passing it tovalue(ReactiveValue).If current
ReactiveValueis actually changed as determined byequality()setting,version()is incremented and dependent reactive computations (the ones that accessedvalue()orget()) are notified about the change. Note that change is detected if the oldReactiveValuehasReactiveValue.blocking()flag set or if it holds an exception (ReactiveValue.exception()). If there is no actual change (newReactiveValuecompares equal to the oldReactiveValueperequality()setting), then the state of thisReactiveVariabledoes not change, oldReactiveValueis kept,version()remains the same, and no change notifications are sent.- Parameters:
-
value- new value to store in thisReactiveVariable - See Also:
-
keepalive
Adds strong reference to the specified target object. This is sometimes useful to control garbage collection. Only one target object is supported. If this method is called twice, the first target is discarded.Hookless keeps strong references in the direction from reactive computations to their reactive dependencies and weak references in opposite direction. This usually results in expected garbage collector behavior.
However, when
ReactiveVariableis embedded in a higher level reactive object, reactive computations hold strong references to the embeddedReactiveVariableinstead of pointing to the outer reactive object, which makes the outer object vulnerable to premature collection. If the outer object is supposed to exist as long as its embeddedReactiveVariableis referenced, for example when it hasReactiveTriggersubscribed to changes in theReactiveVariable, the outer object should call this method on its embeddedReactiveVariable, passing itself as the target object. This will ensure the outer object will live for as long as its embeddedReactiveVariable.- Parameters:
-
keepalive- target object that will be strongly referenced by thisReactiveVariable - Returns:
-
this(fluent method)
-
toString
Returns diagnostic string representation of thisReactiveVariable. StoredReactiveValueis included in the result, but no reactive dependency is created by calling this method.- Overrides:
-
toStringin classObject - Returns:
-
string representation of this
ReactiveVariable
-