Welcome to the heart of Flutter development: Widgets! If you've ever built an application with any framework, you're likely familiar with the concept of UI elements. In Flutter, everything you see on the screen – from a simple text label to a complex navigation bar – is a widget. But what truly sets Flutter's widget philosophy apart is its fundamental approach: widgets are immutable descriptions of your UI. This means that when you create a widget, you're not directly manipulating pixels on the screen. Instead, you're declaring what your UI should look like at any given moment.
Think of it like this: you're not telling a painter to 'draw a blue circle here'. You're providing a blueprint that says, 'At this position, there should be a blue circle.' When the underlying data changes (e.g., a user clicks a button), Flutter doesn't try to modify the existing widget. Instead, it rebuilds the relevant parts of the widget tree with a new blueprint, and Flutter's rendering engine efficiently updates the screen to match the new description. This immutability simplifies state management and leads to highly performant UIs.
Flutter classifies widgets into two main categories:
- Stateless Widgets: These widgets are immutable and their state cannot change after they are built. They are perfect for static content or UI elements that don't need to react to user input or data changes. Examples include text labels, icons, and basic layout containers.
class MyStatelessWidget extends StatelessWidget {
const MyStatelessWidget({super.key});
@override
Widget build(BuildContext context) {
return const Text('This is a stateless widget');
}
}- Stateful Widgets: These widgets are mutable and can change their appearance or behavior over time in response to user interaction or data updates. They maintain their state internally, allowing for dynamic UIs. Examples include checkboxes, text fields, and animations.
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({super.key});
@override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Column(children: [
Text('You have pushed the button this many times: $_counter'),
ElevatedButton(onPressed: _incrementCounter, child: const Text('Increment'))
]);
}
}