Flutter State Management: Stateful vs Stateless Widgets
In Flutter, state management is crucial for creating interactive UIs, and it often begins with understanding the difference between Stateless and Stateful widgets. Here’s a deep dive into both concepts and how Flutter state management plays a pivotal role in Flutter development.

What is State?
In Flutter, the state represents data that can change over time. This could be anything, from user inputs to data fetched from an API. Managing this state determines how your app behaves.


Stateless Widgets
Stateless widgets are immutable, meaning they don’t change once built. When a stateless widget’s state needs to be updated, the entire widget has to be rebuilt. These widgets are often used for static content like text, icons, or images.
- Example:
class MyStatelessWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text('I am Stateless');
}
}
Here, MyStatelessWidget
doesn’t change. It’s perfect for content that doesn’t rely on any state change.
Stateful Widgets
On the other hand, stateful widgets can change their state dynamically. They are used when the UI should change based on some interaction or data.
- Example:
class MyStatefulWidget extends StatefulWidget {
@override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int counter = 0;
void increment() {
setState(() {
counter++;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('Counter: $counter'),
ElevatedButton(
onPressed: increment,
child: Text('Increment'),
),
],
);
}
}
In this example, the counter
state is updated each time the button is pressed, and the UI reflects the changes.
Stateful vs Stateless Comparison
- Stateless Widgets: Used for static content, doesn’t change once built.
- Stateful Widgets: Used for dynamic content, the UI can change as state changes.
State Management Approaches in Flutter
Managing state becomes tricky when your app grows in complexity. Flutter provides multiple ways to manage state, from simple built-in approaches to third-party solutions.
- setState(): The simplest method where you manage state locally within a single widget.
- InheritedWidget: For sharing state across widget trees.
- Provider: A more scalable solution that works well with larger apps. It uses inherited widgets under the hood but simplifies their usage.
- BLoC (Business Logic Component): A reactive state management approach that separates UI and business logic using streams and sinks.
- Riverpod: An improvement over
Provider
, offering better performance and testability.
Stateful and Stateless in Practice
Let’s say we want to build a simple counter app. We can use a stateful widget to update the counter each time a button is pressed.
class CounterApp extends StatefulWidget {
@override
_CounterAppState createState() => _CounterAppState();
}
class _CounterAppState extends State<CounterApp> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Counter App'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('You have pushed the button this many times:'),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
ElevatedButton(
onPressed: _incrementCounter,
child: Text('Increment'),
),
],
),
),
);
}
}
When the ElevatedButton
is pressed, the _incrementCounter
method is called, and the UI is rebuilt with the new counter value.
Managing State Efficiently
When building complex apps, managing state within a single widget can become tedious. Flutter provides several tools and packages that help handle the state more efficiently, especially across multiple widgets or pages.
- setState(): While good for small, localized state changes, it becomes impractical for larger apps.
- InheritedWidget: A built-in Flutter feature that allows sharing state across the widget tree.
- Provider: The most popular Flutter state management solution in Flutter. It simplifies the management of state and works well for large apps.
Using Provider for State Management
Let’s introduce a new concept: Provider. This package simplifies managing state globally. Here’s how it works with a counter app:
- Define a ChangeNotifier class:
class Counter with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
2. Use Provider in your app:
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => Counter(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final counter = Provider.of<Counter>(context);
return Scaffold(
appBar: AppBar(title: Text('Provider Counter')),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Counter: ${counter.count}'),
ElevatedButton(
onPressed: counter.increment,
child: Text('Increment'),
),
],
),
);
}
}
In this example, Provider
manages the state for us. The Counter
class is injected into the widget tree, and any widget can access its state.
Conclusion
State management is a fundamental part of building Flutter apps. Understanding when to use Stateless and Stateful widgets is crucial, but as your app grows, adopting state management solutions like Provider or BLoC will make your code more maintainable. Keep experimenting with different Flutter state management techniques to find the one that suits your app best.
Frequently Asked Questions (FAQs)
- What is the difference between stateless and stateful widgets?
- Stateless widgets cannot change once built, while stateful widgets can rebuild themselves based on state changes.
- What is setState in Flutter?
setState
is used in stateful widgets to update the state and refresh the UI.
- When should I use Provider?
- Provider is used when you need to manage state across multiple widgets or pages efficiently.
- What is the Bloc pattern?
- Bloc (Business Logic Component) separates business logic from the UI, making it easier to manage complex state changes with streams.
Explore Other Flutter Topics…
- Introduction to Flutter and Dart
- Why choose Flutter
- Installing Flutter On Your Windows Mac And Linux System
- Your first Flutter app
- Flutter project structure
- Building blocks of Flutter
- Stateful vs. Stateless Widgets Explained
- Flutter layout system
- Flutter text widget
- Creating Buttons in Flutter: ElevatedButton, TextButton, and IconButton
- Handling User Input with Flutter Forms
- Container class in Flutter
- Flutter Navigation
- Flutter – Pass Data One Screen To Another Screen
- Managing Device Orientation in Flutter
- Stateful widget lifecycle in Flutter
- Future of Flutter
- Flutter Themes
- Flutter Animations
- Flutter AppBar Customization
- ListView in Flutter
- Flutter GridView
- Flutter Expanded Widget
- Flutter BottomNavigation Bar
- Floating Action Button
- Drawer Widgets in Flutter
- Form Validation in Flutter
- Flutter TextField
- Adding AdMob ads to a Flutter app
- Building Flutter Web & Desktop Applications
- What is Async and Await in Flutter
- HTTP requests in Flutter
- Parsing JSON in Flutter
- Tinder-Style Swipe Cards in Flutter
- Flutter Tic Tac Toe Game Tutorial
- Flutter Login UI Tutorial
- Flutter Card Widget Tutorial
- Flutter music player app tutorial
- Flutter introduction screens
- Shared Preferences in Flutter
- SQLite Database in Flutter
- Firebase Authentication in Flutter
- Firebase Firestore in Flutter
- Push Notifications in Flutter
- Handling File Uploads in Flutter
- Responsive Design in Flutter
- Provider in Flutter
- Riverpod in Flutter
- Flutter BLoC Pattern Tutorial