3.9 KiB
State Management in Flutter: A Comprehensive Guide
State management is a crucial aspect of Flutter development. It involves managing the data and UI state of your application efficiently. This guide covers some popular state management approaches in Flutter.
1. Provider
Provider is a wrapper around InheritedWidget to make them easier to use and more reusable.
Example:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class CounterModel extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => CounterModel(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Provider Example')),
body: Center(
child: Consumer<CounterModel>(
builder: (context, counter, child) => Text(
'Count: ${counter.count}',
style: TextStyle(fontSize: 24),
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => Provider.of<CounterModel>(context, listen: false).increment(),
child: Icon(Icons.add),
),
),
);
}
}
2. Riverpod
Riverpod is a complete rewrite of Provider to make it more type-safe and able to catch programming errors at compile time.
Example:
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
final counterProvider = StateNotifierProvider<Counter, int>((ref) => Counter());
class Counter extends StateNotifier<int> {
Counter() : super(0);
void increment() => state++;
}
void main() {
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Riverpod Example')),
body: Center(
child: Text(
'Count: $count',
style: TextStyle(fontSize: 24),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => ref.read(counterProvider.notifier).increment(),
child: Icon(Icons.add),
),
),
);
}
}
3. BLoC (Business Logic Component)
BLoC separates the business logic from the UI, making the code more testable and reusable.
Example:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
// Events
abstract class CounterEvent {}
class IncrementEvent extends CounterEvent {}
// BLoC
class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc() : super(0) {
on<IncrementEvent>((event, emit) => emit(state + 1));
}
}
void main() {
runApp(BlocProvider(
create: (context) => CounterBloc(),
child: MyApp(),
));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('BLoC Example')),
body: Center(
child: BlocBuilder<CounterBloc, int>(
builder: (context, count) {
return Text(
'Count: $count',
style: TextStyle(fontSize: 24),
);
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => context.read<CounterBloc>().add(IncrementEvent()),
child: Icon(Icons.add),
),
),
);
}
}
Conclusion
Choosing the right state management solution depends on your app's complexity and your team's preferences. Each approach has its strengths, and understanding these different methods will help you make informed decisions in your Flutter projects.