LiveValue

Un «valor actual» vivo con suscriptores: un suscriptor tardío recibe de inmediato el último valor, y después cada actualización posterior.

class LiveValue<T> { LiveValue(); // empty — subscribers wait for the first add LiveValue.seeded(T value); // starts with a current value LiveValue.from(Stream<T> source); // hot, fed by source LiveValue.seededFrom(T seed, Stream<T> src); // hot, seeded T get value; // latest value; StateError when none set bool get hasValue; bool get isClosed; void add(T value); // set + deliver to subscribers FxEvents<T> get live; // replay the latest, then live updates Stream<T> get stream; // plain-Stream view of live Future<void> close(); } LiveValue<T> Stream<T>.fxLive // = LiveValue.from(stream) LiveValue<T> Stream<T>.fxLiveSeeded(T seed) // = LiveValue.seededFrom(seed, stream)

Lección

Un Stream normal no tiene memoria: suscríbete tarde y no recibes nada hasta el siguiente evento, lo que para el estado — el usuario actual, la temperatura actual, el zoom actual — significa que cada pantalla nueva arranca en blanco. LiveValue<T> es el estado hecho fuente de eventos: guarda un valor actual, add lo actualiza y notifica a los suscriptores, y todo suscriptor tardío recibe primero la repetición del último valor y luego se sube a las actualizaciones en vivo. Sin hueco, sin arranque en blanco, sin «espera al siguiente tic».

La API es deliberadamente pequeña. Construye vacío (LiveValue()) o con semilla (LiveValue.seeded(value)). Lee de forma síncrona con .value — que lanza un StateError cuando no se ha establecido nada, así que comprueba .hasValue o siembra el valor; no hay un null silencioso haciéndose pasar por estado. Suscríbete a través de .live, que es una cadena FxEvents (mapéala, aplícale debounce, combínala), o de .stream para la vista de Stream normal del mismo feed.

close() termina el feed: los streams de los suscriptores se cierran, y un add posterior lanza — aunque incluso un LiveValue cerrado sigue repitiendo su último valor a un suscriptor tardío antes de cerrarle el stream. Si conoces Rx, esto es BehaviorSubject reducido a su comportamiento definitorio; capa de eventos de fxdart, no parte de FxTS.

Demo 1 · Los suscriptores tardíos arrancan desde el último valor

Demo 2 · value, hasValue y close

La forma con método

Un Stream alcanza ambos constructores como miembros: source.fxLive es LiveValue.from(source), y source.fxLiveSeeded(v) es LiveValue.seededFrom(v, source). Los dos siguen siendo calientes: la suscripción se abre en el acto.

final price = ticker.fxLive;
final count = taps.fxLiveSeeded(0);   // has a value before the first tap

Pruébalo tú

Ejercicio: deriva un feed de etiquetas desde estado en vivo.

Relacionado: fxEvents.live habla esta cadena de forma nativa · combineLatest — derivar estado desde dos feeds vivos · Puentes de Stream — llevar el feed al mundo pull