Complete Guide to StatelessWidget and StatefulWidget in Flutter
Wed, March 2025 18:54:12
Flutter is a powerful framework for building mobile, web, and desktop applications from a single codebase. One of the fundamental concepts to master when learning Flutter is understanding the difference and usage of StatelessWidget and StatefulWidget.
In this article, we'll dive deep into these two types of widgets, how to use them, and when to choose one over the other.
1. What is a Widget in Flutter?
Flutter builds UIs using widgets. Every element on the screen — like text, buttons, images, and even layout structures — is a widget. Widgets are like the "building blocks" of an app.
Flutter widgets are declarative, meaning we define the UI based on the state. When the state changes, the UI rebuilds to reflect those changes.
Types of Widgets in Flutter
Flutter has two main types of widgets:
- StatelessWidget — Widgets that do not change (static).
- StatefulWidget — Widgets that can change (dynamic).
Let’s break them down one by one!
2. StatelessWidget: Static Widgets
StatelessWidget is a widget that doesn’t have a mutable state after being built. Its UI remains the same throughout its lifecycle.
Common examples: text, icons, and images displayed without interaction.
Example of a StatelessWidget
import 'package:flutter/material.dart';
class MyStatelessWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Stateless Widget')),
body: Center(
child: Text(
'Hello, I am a StatelessWidget!',
style: TextStyle(fontSize: 24, color: Colors.blue),
),
),
);
}
}
void main() => runApp(MaterialApp(home: MyStatelessWidget()));
Explanation:
- StatelessWidget inherits from the
StatelessWidgetclass. - build() is a required method that constructs the widget’s UI.
- The UI renders once and doesn’t change, even with events or interactions.
When to Use StatelessWidget?
Use StatelessWidget when:
- The content is static and won’t change.
- The displayed data is final or fetched once from an external source.
- The UI elements are purely visual without interactions that affect the state.
Examples of use cases:
- Static text
- App logo
- Navigation icons
- Basic layout structures
3. StatefulWidget: Dynamic Widgets
StatefulWidget is a widget that has state and can change during its lifetime.
State represents data that can change over time, like:
- A counter that increases when a button is pressed.
- A form that updates as you type.
- Animations that move or change.
Structure of StatefulWidget
StatefulWidget consists of two classes:
- Main class (StatefulWidget) → Immutable.
- State class (_State) → Handles the mutable state and logic.
Example of a StatefulWidget
import 'package:flutter/material.dart';
class MyStatefulWidget extends StatefulWidget {
@override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Stateful Widget')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Press the button to increase the number:'),
Text('$_counter', style: TextStyle(fontSize: 30)),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
child: Icon(Icons.add),
),
);
}
}
void main() => runApp(MaterialApp(home: MyStatefulWidget()));
Explanation:
- MyStatefulWidget class → Creates the main widget.
- _MyStatefulWidgetState class → Handles the state and logic.
- setState() → Notifies Flutter that the state has changed, triggering a UI rebuild.
4. StatelessWidget vs StatefulWidget Comparison
| Feature | StatelessWidget | StatefulWidget |
|---|---|---|
| State | Cannot change | Can change |
| UI rebuild | Renders once | Rebuilds on state change |
| Examples | Static text, icons | Counter, interactive forms |
| Performance | Lightweight | Heavier (requires state management) |
5. Lifecycle of StatefulWidget
StatefulWidget has a more complex lifecycle than StatelessWidget. Here’s the flow:
- createState() → Creates a new state.
- initState() → Called once when the state is first created.
- build() → Constructs the UI (can be called multiple times on state changes).
- setState() → Triggers a rebuild.
- dispose() → Cleans up resources when the widget is removed.
Lifecycle example
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
@override
void initState() {
super.initState();
print('Widget created');
}
@override
void dispose() {
print('Widget disposed');
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(child: Text('Stateful Widget Lifecycle'));
}
}
6. Conclusion
Flutter relies on two main widget types: StatelessWidget for static UI and StatefulWidget for dynamic UI that can change.
- StatelessWidget is more lightweight and ideal for fixed displays.
- StatefulWidget offers flexibility and can adapt based on app state.
The key to building efficient Flutter apps is understanding when to use each type of widget and how to manage state properly.
Hope this article helps you dive deeper into Flutter. Happy coding! 🚀