atomic_flutter 0.5.1
atomic_flutter: ^0.5.1 copied to clipboard
A lightweight, reactive state management solution for Flutter applications with async state support and domain-specific atoms.
Changelog #
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.5.1 - 2026-03-22 #
Fixed #
atomicUpdate()rollback — atoms now restore their previous values when an error is thrown inside the update block, preventing inconsistent stateAsyncValue.hasValue— correctly returnstruefor nullable success types withnulldataAsyncValue.value— uses safeas Tcast instead of!to support nullable type parametersAsyncAtom.cancel()/clear()— bypass middleware viasetDirect()to avoid unintended side effectsasStream()— changed to single-subscriptionStreamControllerwith lazy listener setup, preventing resource leaksselect()— now delegates tocomputed()for proper read-only semanticsthrottle()— added trailing-edge emission so the last value in a throttle window is never lostcombine()—onDisposecallbacks now return removal functions; each source properly cleans up the other on disposalpersistAtom()race condition — userset()calls during async storage restore now take priority over the persisted value; restored values no longer trigger a redundant write-backWatchAtommixin — fixed subscription tracking so_watchingis cleared on the firstwatch()of each build pass instead of inside the listenerexecuteWithRetry()— checksisDisposedafter each retry delay to stop retrying disposed atomsAtomFamily.call()— auto-removes disposed atoms from the internal map and returns a fresh instanceAtomFamily.dispose()— snapshots the map before iterating to preventConcurrentModificationErrorAtomHistorylint — replaced!withas Tcasts on nullable type parameters to fixnull_check_on_nullable_type_parameterMultiAtomBuilderequality —_listsEqualnow handles lists of different lengths correctly- Example app — fixed
AsyncBuilder→AsyncAtomBuilder, wrongsuccess:parameter name, andselect()leak inbuild() - CI analysis — excluded
devtools_extension/fromflutter analyzeto prevent false failures from its unresolved dependencies
Added #
Atom.setDirect()—@protectedmethod for cross-library access to bypass middlewareAtom.onDispose()removal — now returns aVoidCallbackto unregister the callback; runs immediately if atom is already disposed- CI workflow — GitHub Actions workflow for
flutter analyzeandflutter teston push/PR tomain - README badge — test status badge
- New tests —
onDisposeremoval,AtomFamilyauto-cleanup,atomicUpdaterollback,AsyncValue.hasValuefor nullable types,persistAtomrace conditions, throttle trailing edge, and more
0.5.0 - 2026-03-18 #
Added #
WatchAtommixin — subscribe to atoms directly insidebuild()with noAtomBuilderwrapper; subscriptions are reconciled automatically after each frameAtomMiddleware— intercept and transform values on everyset()call; supports global middleware (Atom.addMiddleware) and per-atom transformers via themiddlewareconstructor parameterLoggingMiddleware— built-in middleware that logs every state change in debug mode at zero cost in release buildsatomicUpdate()— defers all listener notifications until every atom in the block has been updated; nested calls are fully supported via a depth counterAtomHistory<T>— wraps anyAtom<T>with a bounded undo/redo stack backed by a fixed-capacity ring buffer;canUndoandcanRedoexposed asAtom<bool>for reactive UIpersistAtom()— creates an atom whose value is automatically saved to and restored from anyAtomStoragebackendAtomStorage— storage abstraction withread/write/delete; implement for any key-value store (SharedPreferences, Hive, etc.)InMemoryAtomStorage— in-memoryAtomStorageimplementation for tests- Custom
equalsonAtomSelector— prevents rebuilds when a custom equality function says the selected value has not changed
Changed #
AtomBuilderbuilder signature now includes an optionalchildparameter:Widget Function(BuildContext, T, Widget?)— allows passing a static sub-tree that is not rebuilt on atom changesAsyncAtomBuilderis now the single async widget —AsyncBuilderhas been removed; providingoperationenables both pull-to-refresh and a retry button with no extra flagsselect()extension now returnsAtom<S>(a derived atom) instead of a widgetatomicUpdate()replacesbatchAtomUpdates— the old function has been removed_globalBatchingreplaced by_globalBatchDepthcounter so nestedatomicUpdatecalls flush only when the outermost block exits_isBatchingreplaced by_batchDepthcounter onAtomso nestedbatch()calls on the same atom flush only when the outermost call exits
Fixed #
_notifyListenersnow snapshots the listener set before iterating, preventingConcurrentModificationErrorwhen a listener removes itself during notification- Duplicate atoms in
MultiAtomBuilder's atom list no longer register multiple listeners, preventing a listener leak select()listener now wraps the selector call in a try-catch, consistent withmap()andwhere()
Removed #
AtomConsumer— useAtomBuilderinsteadAsyncBuilder— useAsyncAtomBuilderinsteadbatchAtomUpdates— useatomicUpdateinstead
0.4.0 - 2026-03-17 #
Added #
- DevTools Extension: Built-in Flutter DevTools extension with four feature panels:
- Atom Inspector: Live table of all atoms with search, filtering, and detail view
- Dependency Graph: Interactive force-directed graph visualization of atom dependencies
- Async Timeline: Timeline of AsyncAtom state transitions with duration bars and error details
- Performance Dashboard: Update frequency and widget rebuild rankings with hot atom detection and memory leak warnings
- Settings: Configurable polling intervals and JSON snapshot export
AtomicFlutterDevToolsService— VM service extension layer for DevTools communicationAsyncAtomEventandAsyncEventLog— ring buffer for async state transition recordingWidgetRebuildTracker— tracks AtomBuilder widget rebuild counts per atom- Debug getters on
Atom:debugDependencyIds,debugDependentIds,isComputed,listenerCount enableDebugMode()now automatically registers DevTools service extensions and enables performance monitoring
Changed #
enableDebugMode()now also enablesAtomPerformanceMonitorand registers DevTools service extensions
Notes #
- All DevTools instrumentation is zero-cost when debug mode is off
- No new runtime dependencies — uses only
dart:developerfor service extensions - The extension is bundled with the package — no separate dependency needed
0.3.0 - 2025-12-04 #
Fixed #
Critical Memory Leak Fixes:
- Fixed memory leaks in all core extension methods (
debounce,throttle,map,where,combine) - Fixed memory leaks in all async extension methods (
debounceAsync,mapAsync,chain,cached,asyncMap) - Fixed
StreamControllernot being disposed when atom is disposed inasStream() - All extension methods now properly cleanup listeners in both directions (source → derived and derived → source)
- Timer cleanup added to prevent resource leaks in debounce, throttle, and cached operations
Type Safety & Error Prevention:
- Computed atoms now throw
UnsupportedErrorwhen attempting to mutate viaset()orupdate() - Added circular dependency detection in
computed()with clear error messages - Prevents infinite loops from circular atom dependencies
Robustness & Error Handling:
- Listener errors are now caught and logged instead of crashing the app
- Errors in computed atom recomputation no longer prevent other listeners from executing
- Added try-catch blocks to all extension methods with error logging in debug mode
Edge Cases & API Improvements:
combineAsync()now handles empty list input (returns success with empty list)chain()now propagates initial state correctly (idle/loading/error states)combine()now includes error handling for tuple creation
Added #
- Comprehensive test suite with 31+ new test cases covering:
- Memory leak detection and prevention
- Computed atom mutation attempts
- Circular dependency detection
- Error handling in listeners and computed atoms
- Edge cases in async operations
- Bidirectional cleanup verification
Changed #
- All extension methods now use named listener functions for proper cleanup
- Improved documentation for
combineAsync()explaining behavior with empty lists - Enhanced error messages for computed atom mutations
0.2.3 - 2025-08-11 #
Fixed #
- Clean up whitespace in async widget and test files
- Update async handling and improve code structure
0.2.0 - 2025-08-11 #
Added #
- AsyncAtom: New async state management with
AsyncValue<T>wrapper - AsyncState enum:
idle,loading,success, anderrorstates - AsyncAtomBuilder: Widget for building UI based on async atom states
- AsyncBuilder: Simplified async widget with retry and refresh support
- Async Extensions:
debounceAsync()- Debounced async operationsmapAsync()- Transform async valuesexecuteIfNotLoading()- Conditional executionexecuteWithRetry()- Retry failed operations with exponential backoffchain()- Chain async operationscached()- Create cached async operations with TTLtoAsync()- Convert regular atoms to async atomsasyncMap()- Create async atoms from regular atom changes
- Global Async Functions:
computedAsync()- Create debounced computed async atomscombineAsync()- Combine multiple async atoms
- Memory Management: Enhanced automatic cleanup for async operations
- Debug Support: Extended debug utilities for async atoms
- Comprehensive Test Coverage: Added extensive tests for all new features
Changed #
- Enhanced core
Atomclass with improved async support - Updated extension methods with better async integration
- Improved documentation with async examples
Fixed #
- Async atom test stability improvements
- Memory leak prevention in async operations
0.1.1 - 2025-03-17 #
0.1.0 - 2025-03-17 #
Added #
- Initial beta release
- Core
Atomclass for state management computedfunction for derived state- UI widgets:
AtomBuilder,MultiAtomBuilder, andAtomSelector - Extension methods:
effect,asStream,select,debounce, andthrottle - Automatic memory management with reference counting
- Debug utilities for tracking atom state and changes
- Comprehensive documentation and examples