पाठ 5 / 25
StatelessWidget and StatefulWidget
setState and the State lifecycle.
When the UI depends on changing data
A StatelessWidget depends only on its constructor arguments and inherited data, so it has just a build method. A StatefulWidget pairs an immutable widget with a separate, long-lived State object. Calling setState(() { ... }) inside the State marks it dirty so build runs again on the next frame. Key lifecycle methods: initState (one-time setup, such as creating controllers or subscriptions), didUpdateWidget (the parent passed new configuration), didChangeDependencies (an inherited widget it depends on changed), build, and dispose (release controllers, timers and subscriptions). Use the mounted property to check the State is still in the tree before calling setState after an await.
A counter with lifecycle hooks
StatefulWidget and its State.
class Counter extends StatefulWidget {
const Counter({super.key, this.start = 0});
final int start;
@override
State<Counter> createState() => _CounterState();
}
class _CounterState extends State<Counter> {
late int _count;
@override
void initState() {
super.initState();
_count = widget.start; // read configuration via `widget`
}
void _increment() => setState(() => _count++);
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Text('Count: $_count'),
IconButton(onPressed: _increment, icon: const Icon(Icons.add)),
],
);
}
}Keep state as low as possible
Put StatefulWidgets near the leaves that actually change. Calling setState high in the tree rebuilds everything below it.
त्वरित जाँच: Where should you release a TextEditingController or StreamSubscription?
- In build()
- In dispose()
- In the widget constructor
- Nowhere; Dart frees them automatically
Answer
In dispose() — dispose is the State's cleanup hook; forgetting it leaks listeners and resources.