NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
pub.dev · #3070 most downloaded on pub.dev
ValueListenable operators (map, where, select, debounce, combineLatest) and reactive collections (ListNotifier, MapNotifier, SetNotifier). Formerly known as functional_listener.
Last release 19 days ago
19 Sep 2026
Ships fairly regularly
a new release about every 3 months
Nearly every release is documented
notes for 9 of 9 stable releases
Nothing withdrawn
no release was ever pulled
1 years old
9 releases · first in 2025
Operator chains (map, select, where, debounce, async, combineLatest*, mergeWith and Listenable.debounce) now detach from their source when their last
Operator chains (map, select, where, debounce, async, combineLatest*,
mergeWith and Listenable.debounce) now detach from their source when their
last listener is removed and re-attach on the next listener.
lazy: true) - nothing changes for chains that never had a listener or that
always have at least one.ValueNotifier.addListener re-attaches the chain (cascading up again) and resyncs
its value from the source before the new listener is registered, so the
resync never notifies that listener. Notifications resume on the next change..value is always correct while detached: it is derived from the current
source value on read (map calls convert, select calls selector,
where returns the source value if it passes the filter and its last stored
value otherwise, debounce/async return the source value immediately,
combineLatest* call the combiner). This also applies to lazy: true
chains before their first listener.
mergeWith can't know which of its sources changed last while
detached and keeps the last value it received while it had listeners.dispose() still works on attached and detached chains; debounce now also
cancels a pending timer on dispose/detach.Why: a chain created per widget instance (e.g. inline in a watch_it
selector like watchValue((M m) => m.counter.map(...))) used to stay
subscribed to m.counter forever after the widget was disposed, accumulating
one listener - and one live chain doing work - per widget instance ever built.
History: functional_listener (the predecessor of listen_it) detached on the
last listener until v4.0.0 (Sept 2024), where that was removed because of
functional_listener#13:
after addListener + removeListener, mapped.value no longer followed
source.value. This release re-introduces the detach, but thanks to
derive-on-read the scenario from #13 now works:
final mapped = source.map((v) => v + 1);
mapped.addListener(l);
mapped.removeListener(l);
source.value = 123;
print(mapped.value); // 124 - derived from the source, chain is detached
Thanks to @Feichtmeier for the detach mechanism (#2).
ChainLifecycle mixin holds the shared attach/detach/resync logic used
by FunctionalValueNotifier, the new CombiningValueNotifierBase (base of
CombiningValueNotifier..CombiningValueNotifier6), MergingValueNotifiers
and FunctionalChangeNotifier.pubspec.lock is no longer committed, following the Dart guidelines for library packages.One column per month.
Added AI skill files in skills/ directory for AI coding assistants
skills/ directory for AI coding assistantsRemove generated test folder from example
Remove generated test folder from example
memory_test/ folderRelease v5.3.3: Use absolute GitHub URL for logo
Release v5.3.3: Use absolute GitHub URL for logo
Release v5.3.3: Use absolute GitHub URL for logo
Release v5.3.3: Use absolute GitHub URL for logo
Release v5.3.3: Use absolute GitHub URL for logo
Release v5.3.3: Use absolute GitHub URL for logo
lazy parameter to all operators (addresses issue #1)
lazy parameter to control when chains subscribe to sourceslazy=false) to ensure .value is always correct.value reliable even before adding listenerslazy=true) delays subscription until first listener is added (memory optimization)lazy: true)mergeWith stale value issue
mergeWith only subscribed to sources when a listener was added.value could be stale if sources changed before adding a listener.value updates immediately when any source changes, even without listenersfinal notifier1 = ValueNotifier<int>(0);
final notifier2 = ValueNotifier<int>(100);
final merged = notifier1.mergeWith([notifier2]);
notifier2.value = 200; // Change source WITHOUT listener
print(merged.value); // Now correctly prints 200 (was 0 in v5.2.1)
lazy parameter to FunctionalValueNotifier base classSelectValueNotifier, MapValueNotifier, WhereValueNotifier, DebouncedValueNotifier, AsyncValueNotifierCombiningValueNotifier classes (2-6 sources) with lazy parameterchainInitialized check in all dispose() methods to prevent errors when disposing uninitialized chainslazy_init_chain_test.dart to pass lazy: true for mergeWithlazy_value_test.dart demonstrates the fix with output showing correct eager initializationRelease v5.3.3: Use absolute GitHub URL for logo
Release v5.3.3: Use absolute GitHub URL for logo
fallbackValue parameter to where() operator
fallbackValue is used if the initial value doesn't match the filter conditionsource.where((x) => x.isEven, fallbackValue: 0)fallbackValue behavior:
NEW FEATURE: Merged with listenable_collections
NEW FEATURE: Merged with listenable_collections
This release merges the listenable_collections package into listen_it, creating a unified package for reactive primitives in Flutter.
listen_it functionality remains unchangedListNotifier, MapNotifier, and SetNotifier from listenable_collections
ValueListenable and ValueListenableBuilderIf you were using listenable_collections, migration is simple:
pubspec.yaml: Replace listenable_collections with listen_it: ^5.1.0import 'package:listenable_collections/listenable_collections.dart'; to import 'package:listen_it/listen_it.dart';listen_it.dart): Includes both operators and collectionscollections.dart): Collections onlycollection: ^1.17.2 dependency (required for collections)Although this version doesn't add any new functionality but is just the rebranding of the original functional_listener package I decided to keep the v
Your coding agent can read these notes before it upgrades. Set up the MCP server →