Welcome to the core of Flutter UI development: Widgets! In Flutter, everything you see on your screen is a widget. Think of them as LEGO bricks that you assemble to build your app's interface. But not all widgets are created equal. Understanding the fundamental difference between StatelessWidget and StatefulWidget is crucial for creating efficient and dynamic applications.
Let's start with StatelessWidget. As the name suggests, these widgets are immutable. This means their properties cannot change after they are created. Once a StatelessWidget is built, it will always look the same until it's rebuilt with new data from its parent. They are perfect for static content, such as labels, icons, or simple layouts that don't need to react to user interaction or data changes.
class MyStaticWidget extends StatelessWidget {
final String title;
const MyStaticWidget({Key? key, required this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text(title);
}
}Now, let's talk about StatefulWidget. These widgets are designed to be dynamic. They can hold mutable state, meaning their properties can change over time. When the state of a StatefulWidget changes, Flutter rebuilds that widget (and potentially its children) to reflect the new state. This is how you create interactive elements like buttons that change appearance, text fields that display user input, or lists that update dynamically.
A StatefulWidget is composed of two parts: the Widget itself (which is immutable, just like a StatelessWidget) and a State object. The State object is where the mutable data lives and where you define the logic for updating that data.
class MyInteractiveWidget extends StatefulWidget {
const MyInteractiveWidget({Key? key}) : super(key: key);
@override
State<MyInteractiveWidget> createState() => _MyInteractiveWidgetState();
}
class _MyInteractiveWidgetState extends State<MyInteractiveWidget> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
ElevatedButton(onPressed: _incrementCounter, child: const Text('Increment'))
],
);
}
}