Question #10MediumFlutter Basics

Statemangment used in flutter

#flutter#state

Answer

Overview

State Management in Flutter handles how data flows through your app and updates the UI when data changes. Flutter offers multiple state management solutions, from built-in options to third-party packages.


Why State Management?

dart
// Problem: Passing data through multiple widgets
HomeScreenProfileScreenSettingsScreenThemeToggle
     ↓ props      ↓ props         ↓ props        ↓ needs data

// Solution: State management - direct access
ThemeToggleProvider/Bloc/GetXGlobal State

Types of State Management

SolutionComplexityLearning CurvePerformancePopularity
setStateVery LowEasyGood⭐⭐⭐⭐⭐
InheritedWidgetMediumModerateExcellent⭐⭐⭐
ProviderLowEasyExcellent⭐⭐⭐⭐⭐
RiverpodMediumModerateExcellent⭐⭐⭐⭐
BLoCHighHardExcellent⭐⭐⭐⭐⭐
GetXLowVery EasyGood⭐⭐⭐⭐
MobXMediumModerateGood⭐⭐⭐
ReduxHighHardGood⭐⭐⭐

1. setState (Built-in)

Overview

Built-in method for local state management in StatefulWidget.

Example

dart
class CounterScreen extends StatefulWidget {
  
  _CounterScreenState createState() => _CounterScreenState();
}

class _CounterScreenState extends State<CounterScreen> {
  int _counter = 0;
  
  void _increment() {
    setState(() {
      _counter++;
    });
  }
  
  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(child: Text('Count: $_counter')),
      floatingActionButton: FloatingActionButton(
        onPressed: _increment,
        child: Icon(Icons.add),
      ),
    );
  }
}

Pros:

  • ✅ No dependencies
  • ✅ Simple for local state
  • ✅ Fast

Cons:

  • ❌ Not scalable
  • ❌ Prop drilling
  • ❌ Hard to test

2. Provider (Recommended)

Overview

Official Flutter state management, built on InheritedWidget.

Installation

yaml
dependencies:
  provider: ^6.0.0

Example

dart
// 1. Create a model
class Counter with ChangeNotifier {
  int _count = 0;
  
  int get count => _count;
  
  void increment() {
    _count++;
    notifyListeners(); // Notify widgets
  }
}

// 2. Provide the model
void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => Counter(),
      child: MyApp(),
    ),
  );
}

// 3. Consume the model
class CounterScreen extends StatelessWidget {
  
  Widget build(BuildContext context) {
    final counter = Provider.of<Counter>(context);
    
    return Scaffold(
      body: Center(child: Text('Count: ${counter.count}')),
      floatingActionButton: FloatingActionButton(
        onPressed: counter.increment,
        child: Icon(Icons.add),
      ),
    );
  }
}

// Alternative: Consumer widget
Consumer<Counter>(
  builder: (context, counter, child) {
    return Text('Count: ${counter.count}');
  },
)

Pros:

  • ✅ Simple API
  • ✅ Official recommendation
  • ✅ Good performance
  • ✅ Easy to test

Cons:

  • ❌ Boilerplate for complex apps
  • ❌ No built-in async handling

3. Riverpod

Overview

Improved version of Provider with compile-time safety.

Installation

yaml
dependencies:
  flutter_riverpod: ^2.0.0

Example

dart
// 1. Create a provider
final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) {
  return CounterNotifier();
});

class CounterNotifier extends StateNotifier<int> {
  CounterNotifier() : super(0);
  
  void increment() => state++;
}

// 2. Wrap app
void main() {
  runApp(ProviderScope(child: MyApp()));
}

// 3. Consume
class CounterScreen extends ConsumerWidget {
  
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(counterProvider);
    
    return Scaffold(
      body: Center(child: Text('Count: $count')),
      floatingActionButton: FloatingActionButton(
        onPressed: () => ref.read(counterProvider.notifier).increment(),
        child: Icon(Icons.add),
      ),
    );
  }
}

Pros:

  • ✅ Compile-time safety
  • ✅ No BuildContext needed
  • ✅ Better testability
  • ✅ Auto-dispose

Cons:

  • ❌ Newer (less community resources)
  • ❌ Steeper learning curve than Provider

4. BLoC (Business Logic Component)

Overview

Reactive state management using Streams.

Installation

yaml
dependencies:
  flutter_bloc: ^8.0.0

Example

dart
// 1. Define events
abstract class CounterEvent {}
class Increment extends CounterEvent {}

// 2. Create BLoC
class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0) {
    on<Increment>((event, emit) => emit(state + 1));
  }
}

// 3. Provide BLoC
BlocProvider(
  create: (context) => CounterBloc(),
  child: MyApp(),
)

// 4. Consume
BlocBuilder<CounterBloc, int>(
  builder: (context, count) {
    return Text('Count: $count');
  },
)

// Dispatch event
context.read<CounterBloc>().add(Increment());

Pros:

  • ✅ Clear separation of logic
  • ✅ Testable
  • ✅ Reactive (Streams)
  • ✅ Enterprise-ready

Cons:

  • ❌ Lots of boilerplate
  • ❌ Steep learning curve
  • ❌ Overkill for small apps

5. GetX

Overview

All-in-one solution: state, navigation, dependencies.

Installation

yaml
dependencies:
  get: ^4.6.0

Example

dart
// 1. Create controller
class CounterController extends GetxController {
  var count = 0.obs; // Observable
  
  void increment() => count++;
}

// 2. Use in widget
class CounterScreen extends StatelessWidget {
  final CounterController c = Get.put(CounterController());
  
  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Obx(() => Text('Count: ${c.count}')),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: c.increment,
        child: Icon(Icons.add),
      ),
    );
  }
}

Pros:

  • ✅ Minimal boilerplate
  • ✅ Easy to learn
  • ✅ Fast development
  • ✅ Built-in navigation

Cons:

  • ❌ Less structured
  • ❌ Global state can be messy
  • ❌ Not recommended by Flutter team

Choosing the Right Solution

For Small Apps (< 10 screens)

setState or Provider

For Medium Apps (10-50 screens)

Provider or Riverpod

For Large/Enterprise Apps

BLoC or Riverpod

For Rapid Prototyping

GetX


Best Practices

Rule: Use the simplest solution that solves your problem

  • ✅ Start with setState
  • ✅ Upgrade to Provider when needed
  • ✅ Use BLoC for complex business logic
  • ✅ Keep state as local as possible
  • ❌ Don't use global state everywhere
  • ❌ Don't mix multiple state management solutions

Resources