set method
Sets the value of this node and notifies all active subscribers.
If newValue is equal to the current value (via ==), this is a
no-op: the value is unchanged and no subscribers are notified.
That includes AsyncData / AsyncLoading / AsyncError when their
payloads compare equal (for example AsyncData(sameUser) twice).
Do not re-set an equal value to kick side effects (resume a deferred scope, re-run sync, refresh listeners). Use invalidate to force a notification without changing the value, or model the signal on a dedicated node / callback instead of piggybacking on identity state.
If the node has been disposed, the call is silently ignored (a concise debug message is printed in debug mode). This soft-fail behavior prevents crashes from late async writes that land after scope disposal.
Implementation
@override
void set(T newValue) {
if (isDisposed) return;
final oldValue = value;
if (oldValue == newValue) return;
final generation = ++_generation;
super.set(newValue);
// A subscriber may dispose this node or synchronously write a newer value.
if (isDisposed || generation != _generation || value == oldValue) return;
try {
final serialized = toStorage(value);
final pending = _writes[storage] ??= {};
final previous = pending[key] ?? Future<void>.value();
final write = previous
.then<void>((_) {}, onError: (Object _, StackTrace _) {})
.then((_) => storage.write(key, serialized));
pending[key] = write;
_lastWrite = write;
write.then(
(_) {
if (generation == _generation) _persistenceError = null;
if (identical(pending[key], write)) pending.remove(key);
},
onError: (Object error, StackTrace stack) {
if (generation == _generation) _persistenceError = error;
if (identical(pending[key], write)) pending.remove(key);
},
);
} catch (error, stack) {
_persistenceError = error;
_lastWrite = Future<void>.error(error, stack)..ignore();
}
}