compose_state 0.1.0 copy "compose_state: ^0.1.0" to clipboard
compose_state: ^0.1.0 copied to clipboard

A Flutter state management package inspired by Jetpack Compose, offering reactive state, centralized ViewModel scoping, API handling, and persistence for basic, complex, and dynamic objects.

Compose State #

A comprehensive Flutter state management package inspired by Jetpack Compose, offering reactive state, centralized ViewModel scoping, API handling, and persistence for basic, complex, and dynamic objects.

pub package License: MIT

๐Ÿš€ Features #

Core State Types #

  • MutableState: Reactive state holder with automatic disposal
  • PersistableState: Built-in persistence with SharedPreferences
  • ApiState: Async data fetching with comprehensive error handling and retry logic
  • DerivedState: Reactive computed states that update automatically
  • HistoryState: Undo/redo support with configurable history size
  • StreamState: Reactive state from Stream sources
  • SignalState: Granular reactivity for performance optimization

Advanced Features #

  • ๐Ÿ›ก๏ธ Comprehensive Error Handling: Configurable error recovery strategies, retry mechanisms, and error boundaries
  • ๐Ÿง  Automatic Memory Management: Weak reference tracking, automatic disposal, and memory leak detection
  • โšก Performance Optimization: Deep equality checking, notification batching, and optimized rebuilds
  • ๐Ÿงช Testing Infrastructure: Mock implementations, state change tracking, and comprehensive testing utilities
  • ๐Ÿ”’ Runtime Type Validation: Type safety for serialization and persistence operations
  • ๐Ÿ”„ State Transactions: Atomic operations across multiple states with rollback support

UI Components #

  • StateBuilder: Reactive UI components that rebuild on state changes
  • OptimizedStateBuilder: Performance-optimized builder with custom equality
  • ErrorBoundary: Graceful error handling in UI components

๐Ÿ“ฆ Installation #

dependencies:
  compose_state: ^0.1.0
#
# ๐Ÿƒ Quick Start

### Basic Counter Example

```dart
import 'package:flutter/material.dart';
import 'package:compose_state/compose_state.dart';

// Create a reactive state
final counter = mutableStateOf(0);

class CounterApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Counter')),
        body: Center(
          child: StateBuilder<int>(
            state: counter,
            builder: (context, count) {
              return Text('Count: $count', style: TextStyle(fontSize: 24));
            },
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () => counter.value++,
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}

Persistent Settings Example #

// Create a persistent state that automatically saves to storage
final themeMode = persistableStateOf<String>(
  'theme_mode',
  defaultValue: 'system',
);

// Usage in widget
StateBuilder<String>(
  state: themeMode,
  builder: (context, mode) {
    return DropdownButton<String>(
      value: mode,
      onChanged: (newMode) => themeMode.value = newMode!,
      items: ['light', 'dark', 'system']
          .map((mode) => DropdownMenuItem(value: mode, child: Text(mode)))
          .toList(),
    );
  },
)

API Data Fetching Example #

// Create an API state with automatic error handling and retry
final userState = apiStateOf<User>(
  () => ApiService.fetchUser(userId),
  errorHandler: StateErrorHandler(
    defaultStrategy: RetryStrategy(maxAttempts: 3),
  ),
);

// Usage in widget
StateBuilder<ApiStateData<User>>(
  state: userState,
  builder: (context, apiData) {
    if (apiData.isLoading) {
      return CircularProgressIndicator();
    }
    
    if (apiData.hasError) {
      return Column(
        children: [
          Text('Error: ${apiData.error}'),
          ElevatedButton(
            onPressed: () => userState.refresh(),
            child: Text('Retry'),
          ),
        ],
      );
    }
    
    final user = apiData.data!;
    return UserProfile(user: user);
  },
)

๐Ÿ“š Documentation #

Core Concepts #

State Types #

MutableState

Basic reactive state with automatic disposal and error handling:

final name = mutableStateOf('John');
final age = mutableStateOf(25);

// Listen to changes
name.addListener(() {
  print('Name changed to: ${name.value}');
});

// Update values
name.value = 'Jane';
age.value = 30;

PersistableState

State that automatically persists to storage:

final settings = persistableStateOf<Map<String, dynamic>>(
  'app_settings',
  defaultValue: {'theme': 'light', 'notifications': true},
  serializer: (value) => value,
  deserializer: (json) => Map<String, dynamic>.from(json),
);

// Changes are automatically saved
settings.value = {'theme': 'dark', 'notifications': false};

ApiState

Handles asynchronous operations with comprehensive error handling:

final postsState = apiStateOf<List<Post>>(
  () => ApiService.fetchPosts(),
  errorHandler: StateErrorHandler(
    defaultStrategy: RetryStrategy(
      maxAttempts: 3,
      backoffMultiplier: 2.0,
    ),
  ),
);

// Check state
if (postsState.isLoading) { /* show loading */ }
if (postsState.hasError) { /* show error */ }
final posts = postsState.data; // Access data

DerivedState

Computed state that automatically updates when dependencies change:

final firstName = mutableStateOf('John');
final lastName = mutableStateOf('Doe');

final fullName = derivedStateOf(() => '${firstName.value} ${lastName.value}');

print(fullName.value); // "John Doe"

firstName.value = 'Jane';
print(fullName.value); // "Jane Doe" (automatically updated)

HistoryState

State with undo/redo capabilities:

final textState = historyStateOf('Initial text');

textState.value = 'Modified text';
textState.value = 'Final text';

textState.undo(); // Back to "Modified text"
textState.undo(); // Back to "Initial text"
textState.redo(); // Forward to "Modified text"

Advanced Features #

Error Handling

Comprehensive error handling with recovery strategies:

final errorHandler = StateErrorHandler(
  defaultStrategy: RetryStrategy(maxAttempts: 3),
  fallbackStrategy: FallbackStrategy(fallbackValue: 'default'),
  onError: (error, context) {
    // Custom error logging
    print('State error: $error');
  },
);

final state = mutableStateOf('value', errorHandler: errorHandler);

Memory Management

Automatic memory management with leak detection:

// Get memory statistics
final stats = StateManager.instance.getMemoryStats();
print('Active states: ${stats.activeStates}');

// Detect potential memory leaks
final leaks = StateManager.instance.detectPotentialLeaks();
if (leaks.isNotEmpty) {
  print('Potential leaks detected: $leaks');
}

// Perform garbage collection
StateManager.instance.performGarbageCollection();

Transactions

Atomic operations across multiple states:

final transactionManager = TransactionManager();

await transactionManager.executeTransaction((transaction) async {
  state1.setValueInTransaction('value1', transaction);
  state2.setValueInTransaction('value2', transaction);
  
  // If any operation fails, all changes are rolled back
  await someAsyncOperation();
});

Performance Optimization

Deep equality checking and notification batching:

// Custom equality for complex objects
final complexState = mutableStateOf(
  MyComplexObject(),
  equalityChecker: EqualityChecker<MyComplexObject>(
    customEquals: (a, b) => a.id == b.id,
  ),
);

// Batch multiple changes to reduce rebuilds
final batcher = NotificationBatcher();
batcher.batch(() {
  state1.value = 'new value 1';
  state2.value = 'new value 2';
  state3.value = 'new value 3';
});

๐Ÿงช Testing #

Compose State includes comprehensive testing utilities:

import 'package:compose_state/testing.dart';

void main() {
  group('State Tests', () {
    test('mock state behavior', () {
      final mockState = mockStateOf(42);
      
      // Control behavior
      mockState.throwOnSet();
      expect(() => mockState.value = 100, throwsException);
      
      mockState.returnValue(200);
      expect(mockState.value, 200);
    });
    
    test('state change tracking', () async {
      final state = mutableStateOf(0);
      final tracker = createStateTracker();
      
      tracker.trackState('counter', state);
      tracker.startTracking();
      
      state.value = 1;
      state.value = 2;
      
      final history = tracker.getChangeHistory('counter');
      expect(history.length, 3); // initial + 2 changes
    });
  });
}

๐Ÿ”„ Migration #

Migrating from other state management solutions? Check our Migration Guide for detailed instructions on migrating from:

  • Provider
  • Bloc
  • Riverpod
  • GetX
  • Previous versions of compose_state

๐Ÿค Contributing #

We welcome contributions! Please see our Contributing Guide for details.

๐Ÿ“„ License #

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ™ Acknowledgments #

  • Inspired by Jetpack Compose's state management
  • Built with Flutter's reactive principles
  • Community feedback and contributions

Made with โค๏ธ for the Flutter community

3
likes
130
points
38
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A Flutter state management package inspired by Jetpack Compose, offering reactive state, centralized ViewModel scoping, API handling, and persistence for basic, complex, and dynamic objects.

Homepage
Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, shared_preferences

More

Packages that depend on compose_state