Flutter State Management
Managing state in Flutter apps with setState, Provider, and Riverpod.
setState - Local State
Stateful Widget
class Counter extends StatefulWidget {
@override
_CounterState createState() => _CounterState();
}
class _CounterState extends State {
int _counter = 0;
void _increment() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Text("$_counter");
}
}
Provider - Recommended
Install Provider
dependencies:
provider: ^6.0.0
Create Model
class Counter with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
Provide
ChangeNotifierProvider(
create: (context) => Counter(),
child: MyApp(),
)
Consume
Consumer<Counter>(
builder: (context, counter, child) {
return Text("${counter.count}");
}
)
Read value
context.read<Counter>().increment();
Watch value
final counter = context.watch<Counter>();
Riverpod - Modern
Install Riverpod
dependencies:
flutter_riverpod: ^2.0.0
Create Provider
final counterProvider = StateProvider((ref) => 0);
Setup ProviderScope
void main() {
runApp(
ProviderScope(
child: MyApp(),
),
);
}
ConsumerWidget
class Home extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Text("$count");
}
}
Update state
ref.read(counterProvider.notifier).state++;
BLoC Pattern
Install flutter_bloc
dependencies:
flutter_bloc: ^8.0.0
Create Event
abstract class CounterEvent {}
class Increment extends CounterEvent {}
Create BLoC
class CounterBloc extends Bloc {
CounterBloc() : super(0) {
on<Increment>((event, emit) {
emit(state + 1);
});
}
}
Provide BLoC
BlocProvider(
create: (context) => CounterBloc(),
child: MyApp(),
)
BlocBuilder
BlocBuilder<CounterBloc, int>(
builder: (context, state) {
return Text("$state");
}
)
Comparison
setState
✓ Simple, built-in
✓ Good for local state
✗ Not scalable
✗ No separation of concerns
Provider
✓ Recommended by Flutter team
✓ Simple API
✓ Good performance
✓ Easy to learn
Riverpod
✓ Modern, compile-safe
✓ No BuildContext needed
✓ Better testing
✗ Steeper learning curve
BLoC
✓ Predictable state
✓ Great for complex apps
✗ More boilerplate
✗ Harder to learn