ScopedObserverMixin mixin
Mixin for plain Dart classes (controllers, stores, services) that own
reactive resources and want them disposed with a single call — the
pure-Dart counterpart of ObserverStateMixin, with no State, no
BuildContext, and no package:flutter import.
Everything created inside scoped (a Computed, an effect(), a
worker) is registered in this object's internal ReactiveScope; any
other Disposer-shaped resource can be registered via autoDispose —
the same name and shape as ObserverStateMixin.autoDispose, kept
deliberately symmetric. Call disposeScope from your own teardown
method (a close(), dispose(), onClose(), ...) to release all of
it at once, in reverse registration (LIFO) order.
scoped(fn) was chosen (over an initState-style lifecycle hook)
because plain Dart classes have no framework-managed lifecycle to hang
such a hook on — a regular method that wraps any code block composes
with constructors, late final field initializers, and ordinary
methods alike, which is exactly how controllers create resources in
practice.
The internal scope is created lazily, on the first use of any member of
this mixin. If that first use happens to run inside another scope's
run(), this scope becomes its child (see ReactiveScope's nesting
note); typically controllers are constructed outside any run() and no
nesting occurs.
Mixin para classes Dart puras (controllers, stores, services) que
possuem recursos reativos e querem descartá-los com uma única chamada —
a contraparte em Dart puro do ObserverStateMixin, sem State, sem
BuildContext e sem import de package:flutter.
Tudo que for criado dentro de scoped (um Computed, um effect(),
um worker) é registrado no ReactiveScope interno deste objeto;
qualquer outro recurso com forma de Disposer pode ser registrado via
autoDispose — mesmo nome e forma de ObserverStateMixin.autoDispose,
mantidos deliberadamente simétricos. Chame disposeScope no seu
próprio método de teardown (um close(), dispose(), onClose(),
...) para liberar tudo de uma vez, em ordem inversa de registro (LIFO).
scoped(fn) foi a escolha (em vez de um gancho de ciclo de vida ao
estilo initState) porque classes Dart puras não têm um ciclo de vida
gerenciado por framework onde pendurar esse gancho — um método comum
que envolve qualquer bloco de código compõe igualmente com
construtores, inicializadores de campo late final e métodos comuns,
que é exatamente como controllers criam recursos na prática.
O escopo interno é criado preguiçosamente, no primeiro uso de qualquer
membro deste mixin. Se esse primeiro uso acontecer dentro do run() de
outro escopo, este escopo vira filho dele (ver a nota de aninhamento
de ReactiveScope); tipicamente controllers são construídos fora de
qualquer run() e nenhum aninhamento ocorre.
Example / Exemplo:
class CounterController with ScopedObserverMixin {
final a = Observable<int>(1);
final b = Observable<int>(2);
late final Computed<int> total =
scoped(() => Computed(() => a.value + b.value));
CounterController() {
scoped(() {
effect(() => print('total: ${total.value}'));
ever(a, (_) => save());
});
}
void close() => disposeScope();
}
Properties
- hashCode → int
-
The hash code for this object.
no setterinherited
- isScopeDisposed → bool
-
Whether disposeScope has already been called.
no setter
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- scope → ReactiveScope
-
The internal ReactiveScope owning every resource this mixin
registered. Exposed for advanced composition (e.g. handing it to a
child object, or manual inspection); most code only needs scoped,
autoDispose and disposeScope.
latefinal
Methods
-
autoDispose(
Disposer disposer) → void -
Registers
disposerto be called by disposeScope — same shape and intent asObserverStateMixin.autoDispose, for resources the scope does not capture on its own (asubscription.cancel, anobservable.close, ...). Sugar forscope.add(disposer), including its already-disposed behavior (immediate disposal + warning, throw understrictMode). -
disposeScope(
) → void - Disposes everything registered so far, in reverse registration (LIFO) order. Idempotent. Call it from your class's own teardown method.
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
scoped<
R> (R fn()) → R -
Runs
fninside this object's scope and returns its result: everyComputed/effect()/worker created insidefnis disposed by disposeScope. Sugar forscope.run(fn). -
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited