The core read-only reactive state interface in the Bloom reactive DAG engine.
Under the strict Producer/Consumer Separation (Has-a) architecture:
- Bloom represents the observation-only view of a reactive node.
- It does NOT implement BloomState or BloomController directly on its public interface.
- Mutation APIs (
.set(),.data =,.setGuarded(),.setError(),.empty([reason])) are strictly confined to BloomController and RawBloomController. - Bloom NEVER implements BloomController, and underlying physical entry nodes are private to the library, preventing rogue downcasting at runtime.
Values and live states are read outside tracking scopes via the global untracked functor
(untracked for values, BloomUntracked.state for live states), and explicitly tracked
within derivation closures via injected BloomVia (via(node) for values, via.state(node) for live states).
System Architectural Flow
1. 3-State Finite State Machine (Observed via untracked.state)
┌────────────────────────────────────────┐
│ Bloom<T> 3-State State Machine │
└────────────────────────────────────────┘
│ (Bloom.empty<T>() or uninitialized)
▼
┌──────────────┐ Controller .set(data) ┌──────────────┐
│ EMPTY │ ───────────────────────────> │ DATA │ (hasData == true)
│ (isEmpty) │ <─────────────────────────── │ (payload:T) │
└──────┬───────┘ Controller .empty([reason])└──────┬───────┘
│ │
│ Controller .setError() Controller │
│ .setError() │
▼ ▼
┌────────────────────────────────────────────────────────────┐
│ ERROR │ (hasError == true)
│ (payload: Object, [StackTrace]) │
└────────────────────────────────────────────────────────────┘
2. Explicit Dependency Registration vs. Raw Reads
[computed / Effect.via Scope]
│ (Injected BloomVia parameter)
▼
via(sourceBloom) ──> [Registers Source Edge in Active LPDAG & Evaluates T]
via.state(sourceBloom) ──> [Registers Source Edge & Returns Live BloomState<T>]
[Outside Derivation Scope / Raw Read]
│
untracked(sourceBloom) ──> [Pure Direct Field Dereference: Returns T (Zero Overhead)]
untracked.state(sourceBloom) ──> [Zero-Allocation Live BloomState<T> View]
Key Invariants & Architectural Benefits
- Zero-Overhead Raw Reads & Explicit Tracking: Reading via untracked
is a pure field dereference with zero tracking overhead and no dynamic
tracking stack penalty. Reactive derivations explicitly declare dependencies via the injected
BloomVia parameter (
via(node)). - 3-State Exclusivity: A Bloom node's observed state is strictly in one of three mutually exclusive states:
- Data (BloomState.hasData == true): Contains a valid payload of type
T(includingnullforT?). - Empty (BloomState.isEmpty == true): Uninitialized or dormant state with optional BloomState.emptyReason.
- Error (BloomState.hasError == true): Exception state encapsulating BloomState.error and optional BloomState.stackTrace.
- Data (BloomState.hasData == true): Contains a valid payload of type
- Sound Fail-Fast Extraction: Reading via untracked while in Empty or Error state throws
BloomSnapshotExtractionException. Use
untracked.state(node).dataOrNull,untracked.state(node).dataOrElse(), or native Dart 3switch (untracked.state(node).phase)for safe total pattern matching.
Warning (Anti-Pattern Prevention):
- Do NOT read reactive nodes untracked directly inside a computed or
Effect.viascope without wrapping invia(...), as untracked intentionally bypasses dependency registration. - Do NOT mutate a BloomController inside a computed or effect reading that same node without a terminating condition, as this induces topological reentrancy cycles.
BAD:
// [Anti-Pattern] Reading untracked without via() bypasses dependency registration
final badComputed = computed((via) {
return untracked(count.bloom) * 2; // count is NOT tracked!
});
GOOD:
// [Recommended] Explicitly register dependencies through via()
final goodComputed = computed((via) {
return via(count.bloom) * 2; // Dynamically and explicitly registered in LPDAG
});
Examples
final counter = blooming(0);
final doubled = computed((via) => via(counter.bloom) * 2);
print(untracked(doubled)); // 0
counter.data = 5;
print(untracked(doubled)); // 10
- Implemented types
- Available extensions
- BloomComputationExtension
- BloomDebugExtension
- BloomEffectExtension
- BloomFlutterExtension
- BloomIterableBloomExtension
- BloomIterableBloomNumericExtension
- BloomIterableComputationExtension
- BloomIterableElementsExtension
- BloomKeyedIterableElementsExtension
- BloomListElementsExtension
- BloomListenableExtension
- BloomMapElementsExtension
- BloomProvideExtension
- BloomSetElementsExtension
Constructors
- Bloom.constant(T data)
-
Creates a constant static leaf node holding an immutable valid
datapayload.factory - Bloom.empty([Object? emptyReason])
-
Creates a constant static leaf node permanently in an uninitialized (Empty) state.
factory
- Bloom.error(Object error, [StackTrace? stackTrace])
-
Creates a constant static leaf node permanently in an Error state.
factory
-
Bloom.future(Future<
T> future, {T initialFactory()?, T onError(Object error, [StackTrace? stackTrace])?}) -
Creates a reactive Bloom node from a Dart Future.
factory
-
Bloom.stream(Stream<
T> stream, {T initialFactory()?, T onError(Object error, [StackTrace? stackTrace])?, bool? cancelOnError, bool distinct = true, bool equals(T previous, T next)?, Graceful? graceful}) -
Creates a reactive Bloom node from a Dart Stream.
factory
Properties
-
build
→ BloomBuildFunctor<
T> -
Available on Bloom<
Entry point for inline single-node reactive UI build functors (BloomBuildFunctor).T> , provided by the BloomFlutterExtension extensionno setter - debug → BloomDebug
-
Available on Bloom<
Access point for zero-overhead node inspection and diagnostics.T> , provided by the BloomDebugExtension extensionno setter - debugCreationLocation → String?
-
Available on Bloom<
The exact code location where this object was created in debug mode.T> , provided by the BloomDebugExtension extensionno setter - debugLabel ↔ String?
-
Available on Bloom<
A developer-defined label to identify this specific object in debug mode.T> , provided by the BloomDebugExtension extensiongetter/setter pair - debugSourceCount → int
-
Available on Bloom<
The number of active upstream source edges connected to this node for verification and testing.T> , provided by the BloomDebugExtension extensionno setter - debugVersion → int
-
Available on Bloom<
The internal version of this Bloom for verification and debugging.T> , provided by the BloomDebugExtension extensionno setter - effect → UnaryBloomEffectScope
-
Available on Bloom, provided by the BloomEffectExtension extension
Opens a scoped namespace for declarative reactive Effect creation targeting this node.no setter -
elements
→ BloomIterableElements<
E> -
Available on Bloom<
Opens a dedicated namespace for operating on the individual elements of this Iterable reactively.Iterable< , provided by the BloomIterableElementsExtension extensionE> >no setter -
elements
→ BloomListElements<
E> -
Available on Bloom<
Opens a dedicated namespace for operating on the individual elements of this List reactively.List< , provided by the BloomListElementsExtension extensionE> >no setter -
elements
→ BloomMapElements<
K, V> -
Available on Bloom<
Opens a dedicated namespace for operating on the individual elements of this Map reactively.Map< , provided by the BloomMapElementsExtension extensionK, V> >no setter -
elements
→ BloomSetElements<
E> -
Available on Bloom<
Opens a dedicated namespace for operating on the individual elements of this Set reactively.Set< , provided by the BloomSetElementsExtension extensionE> >no setter - hashCode → int
-
The hash code for this object.
no setterinherited
- isActive → bool
-
Whether the node is currently active (connected to a downstream terminal).
no setterinherited
-
keyed
→ BloomKeyedIterableElements<
E> -
Available on Bloom<
Opens a dedicated namespace for operating on keyed elements of this Iterable reactively.Iterable< , provided by the BloomKeyedIterableElementsExtension extensionE> >no setter -
listen
→ BloomListenFunctor<
T> -
Available on Bloom<
Entry point for inline zero-rebuild side-effect listener functors (BloomListenFunctor).T> , provided by the BloomFlutterExtension extensionno setter - runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
Methods
-
aggregate<
R> (R aggregator(Iterable< T> elements)) → Bloom<R> -
Available on Bloom<
Reduces multiple inbound elements into a reactive Bloom<R>.Iterable< , provided by the BloomIterableComputationExtension extensionT> > -
any(
[bool predicate(T item)?]) → Bloom< bool> -
Available on Bloom<
Evaluates whether at least one element in the collection satisfiesIterable< , provided by the BloomIterableBloomExtension extensionBloom< >T> >predicate. -
coalesced(
{bool leading = false, bool trailing = true}) → Bloom< T> -
Available on Bloom<
Coalesces multiple synchronous invalidations into a single microtask flush.T> , provided by the BloomComputationExtension extension -
combine(
) → Bloom< List< T> > -
Available on Bloom<
Unifies all member payloads into a reactive Bloom<List<T>>.Iterable< , provided by the BloomIterableBloomExtension extensionBloom< >T> > -
debounced(
Duration duration, {bool leading = false, bool trailing = true}) → Bloom< T> -
Available on Bloom<
Debounces downstream invalidation pulses across quiet periods ofT> , provided by the BloomComputationExtension extensionduration. -
debugTrace(
[String? label, int traceCount = 5]) → void -
Available on Bloom<
Captures the current stack trace and assigns an optional label to this Bloom.T> , provided by the BloomDebugExtension extension -
distinct(
[bool equals(T previous, T next)?]) → Bloom< T> -
Available on Bloom<
Filters out consecutive duplicate payloads usingT> , provided by the BloomComputationExtension extensionequals(or identical / operator ==). -
every(
[bool predicate(T item)?]) → Bloom< bool> -
Available on Bloom<
Evaluates whether every element in the collection satisfiesIterable< , provided by the BloomIterableBloomExtension extensionBloom< >T> >predicate. -
fold<
R> (R initialValue, R combine(R accumulator, T item)) → Bloom< R> -
Available on Bloom<
Folds the payloads of all members into a single reactive Bloom<R>.Iterable< , provided by the BloomIterableBloomExtension extensionBloom< >T> > -
graceful(
[Graceful graceful = Graceful.microtask]) → Bloom< T> -
Available on Bloom<
Buffers deactivation of this node with aT> , provided by the BloomComputationExtension extensiongracefulpolicy when downstream subscribers drop to zero. -
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
provide(
{Key? key, required Widget child}) → BloomProvider< T> -
Available on Bloom<
WrapsT> , provided by the BloomProvideExtension extensionchildin a BloomProvider<T> providing this reactive Bloom node. -
reduce(
T combine(T previous, T current)) → Bloom< T> -
Available on Bloom<
Reduces the payloads of all members into a single reactive Bloom<T>.Iterable< , provided by the BloomIterableBloomExtension extensionBloom< >T> > -
retained(
{BloomCoupler< bool> ? pending}) → Bloom<T> -
Available on Bloom<
Creates a retained node maintaining prior valid data during pending re-evaluations (SWR).T> , provided by the BloomComputationExtension extension -
retainedTuple(
) → ({Bloom< T> data, Bloom<bool> pending}) -
Available on Bloom<
Creates a retained node maintaining prior valid data during pending re-evaluations (SWR), bundled as aT> , provided by the BloomComputationExtension extension({Bloom<T> data, Bloom<bool> pending})record. -
sum(
) → Bloom< T> -
Available on Bloom<
Aggregates all numbers in the collection into their mathematical sum as a reactive Bloom<T>.Iterable< , provided by the BloomIterableBloomNumericExtension extensionBloom< >T> > -
throttled(
Duration duration, {bool leading = true, bool trailing = true}) → Bloom< T> -
Available on Bloom<
Throttles downstream invalidation pulses to at most once perT> , provided by the BloomComputationExtension extensionduration. -
toListenable(
{bool sync = true}) → ValueListenable< T> -
Available on Bloom<
Converts this Bloom into a standard Flutter ValueListenable.T> , provided by the BloomListenableExtension extension -
toString(
) → String -
A string representation of this object.
inherited
-
withDebugLabel<
W extends Bloom< (T> >String label) → W -
Available on Bloom<
Assigns a developer-defined debug label and returns this Bloom.T> , provided by the BloomDebugExtension extension
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited
Static Properties
-
constantNull
→ Bloom<
Null> -
A canonical, immutable static leaf node permanently holding a
nullpayload.final
Constants
- computed → const ComputedFunctor
- Static entrypoint to the computed functor for discoverability and namespace disambiguation.
- managed → const ManagedFunctor
- Static entrypoint to the managed functor for discoverability and namespace disambiguation.
- switched → const SwitchedFunctor
- Static entrypoint to the switched functor for discoverability and namespace disambiguation.