- 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
Modifier and TypeClassDescriptionstatic class
Reference to particular version ofReactiveVariable
. -
Constructor Summary
ConstructorDescriptionCreates new instance withnull
value.ReactiveVariable
(ReactiveValue<T> value) Creates new instance holding specifiedReactiveValue
.ReactiveVariable
(T value) Creates new instance holding specifiedvalue
. -
Method Summary
Modifier and TypeMethodDescriptionboolean
equality()
Returnstrue
if thisReactiveVariable
performs full equality check on assignment.equality
(boolean equality) Configures full or reference equality.get()
Returns the value held by thisReactiveVariable
.int
hashCode()
Returns identity hash code.Adds strong reference to the specified target object.void
Sets current value of thisReactiveVariable
.toString()
Returns diagnostic string representation of thisReactiveVariable
.value()
Reads the currentReactiveValue
from thisReactiveVariable
and sets up reactive dependency.void
value
(ReactiveValue<T> value) Sets currentReactiveValue
of thisReactiveVariable
and notifies dependent reactive computations.long
version()
Returns current version of thisReactiveVariable
.
-
Constructor Details
-
ReactiveVariable
Creates new instance holding specifiedReactiveValue
.- Parameters:
-
value
- initial value of theReactiveVariable
- Throws:
-
NullPointerException
- ifvalue
isnull
-
ReactiveVariable
Creates new instance holding specifiedvalue
. TheReactiveValue
in the newReactiveVariable
will havefalse
ReactiveValue.blocking()
flag.- Parameters:
-
value
- initial value of theReactiveVariable
-
ReactiveVariable
public ReactiveVariable()Creates new instance withnull
value. The newReactiveVariable
will containReactiveValue
withnull
ReactiveValue.result()
.
-
-
Method Details
-
equality
public boolean equality()Returnstrue
if thisReactiveVariable
performs full equality check on assignment. This method merely returns what was last passed toequality(boolean)
. Defaults totrue
.- Returns:
-
true
if full equality check is enabled,false
if reference equality is used - See Also:
-
equality
Configures full or reference equality. When thisReactiveVariable
is assigned, dependent reactive computations are notified about the change if there is any. In order to check whether the stored value has changed,ReactiveVariable
can 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
ReactiveVariable
is used for the first time.- Parameters:
-
equality
-true
to do full equality check,false
to test only reference equality - Returns:
-
this
(fluent method) - See Also:
-
version
public long version()Returns current version of thisReactiveVariable
. EveryReactiveVariable
has 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 currentReactiveValue
from thisReactiveVariable
and sets up reactive dependency.This
ReactiveVariable
is 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
ReactiveValue
of thisReactiveVariable
, nevernull
- See Also:
-
value
Sets currentReactiveValue
of thisReactiveVariable
and notifies dependent reactive computations. This is the more general version ofset(Object)
that allows setting arbitraryReactiveValue
.The
value
may haveReactiveValue.blocking()
flag set and it may containReactiveValue.exception()
. This is useful in situations whenReactiveVariable
is 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 itsReactiveVariable
to a blocking value. It may also communicate exceptions reactively by wrapping them inReactiveValue
and storing it inReactiveVariable
.If current
ReactiveValue
is 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 thisReactiveVariable
does not change, oldReactiveValue
is kept,version()
remains the same, and no change notifications are sent.- Parameters:
-
value
- newReactiveValue
to store in thisReactiveVariable
- Throws:
-
NullPointerException
- ifvalue
isnull
- 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 useReactiveVariable
as 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
ReactiveValue
hasReactiveValue.blocking()
flag set, reactive blocking is propagated into currentReactiveScope
if there is any. If the storedReactiveValue
holds an exception, the exception is propagated wrapped inCompletionException
. Otherwise this method just returnsReactiveValue.result()
.This
ReactiveVariable
is 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 storedReactiveValue
holds 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 wrappingvalue
inReactiveValue
and passing it tovalue(ReactiveValue)
.If current
ReactiveValue
is 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 oldReactiveValue
hasReactiveValue.blocking()
flag set or if it holds an exception (ReactiveValue.exception()
). If there is no actual change (newReactiveValue
compares equal to the oldReactiveValue
perequality()
setting), then the state of thisReactiveVariable
does not change, oldReactiveValue
is 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
ReactiveVariable
is embedded in a higher level reactive object, reactive computations hold strong references to the embeddedReactiveVariable
instead 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 embeddedReactiveVariable
is referenced, for example when it hasReactiveTrigger
subscribed 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
. StoredReactiveValue
is included in the result, but no reactive dependency is created by calling this method.- Overrides:
-
toString
in classObject
- Returns:
-
string representation of this
ReactiveVariable
-