32
Flutter Stateful and Stateless widgets
Yesterday we had a high-level overview of how Flutter works, and learned it uses a widget approach.
Today we'll dive a little bit deeper into the two main types of widgets being:
- Stateful widgets
- Stateless widgets
The state, in general, is information about that widget that can be read once the widget is built. If this never changes, we consider it a stateless widget. If this information can change, it's a stateful widget.
Stateless widgets can never change. Some examples of stateless widgets are Icon
, Text
, and IconButton
.
A stateful widget is dynamic. It might change appearance based on user interaction of when data changes.
Some examples might are TextField
, Checkbox
, and Radio
.
Let's showcase a basic stateless widget that will show some text but not do anything.
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return Center(
child: Text(
'Hello World 👋',
textDirection: TextDirection.ltr,
),
);
}
}
As you can see above, this widget is going to render some text inside a center element.
That's it. That fact won't change no matter what happens.
Stateful widgets are a different story. As mentioned, they might change properties based on data or user action.
Let's use the Flutter demo and create a basic application that will plus a counter when we click a button.
class MyApp extends StatefulWidget {
_MyAppState createState() => _MyAppState();
}
As you can see, we changed the MyApp
to be a stateful widget now.
That means it must implement the createState
function, which in our case calls the _MyAppState
class.
Note: The underscore classes in Dart are considered private!
This new class will extend our basic app state, meaning it can handle change.
class _MyAppState extends State<MyApp> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
),
TextButton(
onPressed: _incrementCounter,
child: const Text('Add number'),
),
]),
),
);
}
}
In there, we define a basic counter variable and set it to zero.
Then we create a function that can increment this number.
Be aware that setState
is needed to make an actual change in a state.
Then we override the widget to create our widget as we did before, but in this one, we get to use a variable text and include a button that will handle an onPressed
event.
So what happens:
- User clicks the button
- _incrementCounter is called
- _incrementCounter adds one to the current number
- state of the app is changed, so re-render app
- text element now shows the new counter value
And this keeps looping on every interaction.
I hope you got a good overview of the difference between stateless and stateful widgets and how they come together in Flutter.
You can find my implementation of the Stateful widget on GitHub.