Stateless vs Stateful Widget Flutter: Key Differences and Usage
StatelessWidget is immutable and does not store any state, so it builds its UI once and never changes. A StatefulWidget can hold mutable state that can change during the widget's lifetime, allowing the UI to update dynamically.Quick Comparison
Here is a quick side-by-side comparison of StatelessWidget and StatefulWidget in Flutter.
| Factor | StatelessWidget | StatefulWidget |
|---|---|---|
| State | No mutable state, UI is static | Has mutable state, UI can update |
| Lifecycle | Built once, no state changes | Built with a State object that can change |
| Use case | Static UI, fixed content | Dynamic UI, user interaction or data changes |
| Performance | Faster, simpler | Slightly heavier due to state management |
| Example | Text label, icon | Checkbox, form input |
Key Differences
A StatelessWidget is a widget that never changes once it is built. It has no internal state to track, so its build() method is called only when the widget is first inserted into the widget tree or when its parent widget changes.
In contrast, a StatefulWidget is paired with a separate State object that holds mutable state. This state can change over time, and when it does, the widget rebuilds its UI by calling setState(). This allows the UI to react to user input, data updates, or animations.
Because StatefulWidget manages state, it has a more complex lifecycle with methods like initState(), dispose(), and didUpdateWidget(), which help manage resources and respond to changes.
Code Comparison
This example shows a simple counter using a StatelessWidget. Notice it cannot update the counter because it has no state.
import 'package:flutter/material.dart'; class CounterStateless extends StatelessWidget { final int count; CounterStateless({required this.count}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Stateless Counter')), body: Center( child: Text('Count: $count', style: TextStyle(fontSize: 24)), ), floatingActionButton: FloatingActionButton( onPressed: () { // Cannot update count here }, child: Icon(Icons.add), ), ); } }
StatefulWidget Equivalent
This example shows the same counter implemented as a StatefulWidget. It updates the count when the button is pressed.
import 'package:flutter/material.dart'; class CounterStateful extends StatefulWidget { @override _CounterStatefulState createState() => _CounterStatefulState(); } class _CounterStatefulState extends State<CounterStateful> { int count = 0; void _increment() { setState(() { count++; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Stateful Counter')), body: Center( child: Text('Count: $count', style: TextStyle(fontSize: 24)), ), floatingActionButton: FloatingActionButton( onPressed: _increment, child: Icon(Icons.add), ), ); } }
When to Use Which
Choose StatelessWidget when your UI does not need to change after it is built, such as static labels, icons, or simple layouts. This keeps your app fast and simple.
Choose StatefulWidget when your UI needs to update dynamically in response to user actions, data changes, or animations. Examples include forms, counters, toggles, and interactive lists.
Using the right widget type helps keep your app efficient and easier to maintain.
Key Takeaways
StatelessWidget for static UI that never changes.StatefulWidget when UI needs to update dynamically.StatefulWidget manages mutable state with a separate State object.