fairy 0.5.0
fairy: ^0.5.0 copied to clipboard
A lightweight MVVM framework for Flutter with strongly-typed, reactive data binding state management library, Mainly focused on simplicity and ease of use.
0.5.0 #
Initial release of Fairy - A lightweight MVVM framework for Flutter.
Features #
Core Primitives
- ObservableObject: Base ViewModel class with clean MVVM API
onPropertyChanged()for manual notificationspropertyChanged(listener)method returning disposer functionsetProperty<T>()helper for batch updates with change detection- Auto-disposal: Properties created during construction are automatically disposed
- ObservableProperty: Strongly-typed reactive properties
- Automatic change notifications with custom equality support
propertyChanged(listener)for subscribing to property changes (returns disposer)- Auto-disposal when parent ObservableObject is disposed
- ComputedProperty: Derived properties with automatic dependency tracking
- Read-only computed values based on other properties
- Automatic updates when dependencies change
- Auto-disposal when parent ObservableObject is disposed
Commands
- RelayCommand: Synchronous commands with optional
canExecutevalidation - AsyncRelayCommand: Asynchronous commands with automatic
isRunningstate - RelayCommandWithParam: Parameterized commands for actions requiring input
- AsyncRelayCommandWithParam: Async parameterized commands
- All commands use named parameters:
execute:,canExecute:,parent: notifyCanExecuteChanged()method to re-evaluatecanExecuteconditionscanExecuteChanged(listener)method for subscribing tocanExecutechanges (returns disposer function)
Dependency Injection
- FairyLocator: Global singleton registry for app-wide services
registerSingleton<T>()for singleton registrationregisterFactory<T>()for factory registrationget<T>()for service resolutionunregister<T>()for cleanup
- FairyScope: Widget-scoped DI with automatic disposal
- Scoped ViewModels auto-disposed when widget tree is removed
- Supports both
createandinstanceparameters
- Fairy (ViewModelLocator): Unified resolution checking scope → global → exception
Fairy.of<T>(context): Idiomatic Flutter API for resolving ViewModels (similar toProvider.of,Theme.of)Fairy.maybeOf<T>(context): Optional resolution returningnullif not found
UI Binding
- Bind<TViewModel, TValue>: Automatic one-way/two-way binding detection
- Returns
ObservableProperty<T>→ two-way binding withupdatecallback - Returns raw
T→ one-way binding (read-only) - Type-safe selector/builder contracts
- Returns
- Command: Command binding with automatic
canExecutereactivity - CommandWithParam<TViewModel, TParam>: Parameterized command binding
Auto-Disposal System
- Parent Parameter: Properties, commands, and computed properties accept optional
parentparameter- Pass
parent: thisin constructor to enable automatic disposal - Children are registered with parent and disposed automatically
- Debug warnings shown when parent is not provided
- Nested ObservableObject instances must be disposed manually
- Pass
Memory Management #
- Auto-disposal: ObservableProperty, ComputedProperty, and Commands automatically disposed when
parentparameter is provided - Nested ViewModels Exception: Nested ObservableObject instances require manual disposal
- Manual Listeners: Always capture disposer from
propertyChanged()andcanExecuteChanged()calls to avoid memory leaks - Use
BindandCommandwidgets for UI (automatic lifecycle management)
Best Practices #
- ⚠️ Memory Leak Prevention: Always capture disposer from manual
propertyChanged()andcanExecuteChanged()calls - Pass
parent: thisto properties, commands, and computed properties for auto-disposal - Nested ViewModels require explicit manual disposal
- Call
command.notifyCanExecuteChanged()whencanExecutedependencies change - Use
command.canExecuteChanged(listener)to listen tocanExecutestate changes - Selectors must return stable property references
- Use
FairyScopefor page-level ViewModels (handles disposal automatically) - Use named parameters for commands:
execute:,canExecute:,parent:
Documentation #
- Comprehensive README with quick start guide
- Auto-disposal explanation and migration patterns
- Complete API reference with examples
- Example app demonstrating MVVM patterns
Testing #
- Comprehensive unit and widget tests with 100% passing rate
- Tests cover all core primitives, DI patterns, UI bindings, and auto-disposal
- Test structure mirrors library organization