Everything you see in a Flutter app is a widget. These four ideas are the foundation of the UI.
A widget is a blueprint for a piece of UI. It is immutable: you do not change a widget after you create it. You create a new one instead.
const Text("Hello Flutter");const Icon(Icons.home);const Padding(padding: EdgeInsets.all(16),child: Text("Hello"),);
Flutter compares the new widget tree with the old one and updates only what changed.
Common widget types:
Column, Row, Padding, CenterText, Image, IconTextField, ElevatedButtonStatelessWidget or StatefulWidgetUse StatelessWidget when the UI depends only on the data it receives. It has no internal state that changes over time.
class Greeting extends StatelessWidget {final String name;const Greeting({super.key, required this.name});@overrideWidget build(BuildContext context) {return Text("Hello $name");}}// usageconst Greeting(name: "Daniel");
It rebuilds when:
InheritedWidget data it depends on changes (for example Theme)If the UI never needs to change by itself, start with StatelessWidget.
Use StatefulWidget when the UI must change after the widget is created — taps, typing, loading, animation.
A stateful widget is two classes:
StatefulWidget → the configuration (immutable, like any widget)State → the mutable data and the build() methodclass Counter extends StatefulWidget {const Counter({super.key});@overrideState<Counter> createState() => _CounterState();}class _CounterState extends State<Counter> {int count = 0;void increment() {setState(() {count++;});}@overrideWidget build(BuildContext context) {return Column(children: [Text("Count: $count"),ElevatedButton(onPressed: increment,child: const Text("Add"),),],);}}
setState() tells Flutter: data changed, call build() again.
Rules:
State, not in the StatefulWidgetsetState() only when the UI should updatesetState() after dispose()build() describes the UI for the current configuration. Flutter calls it when the widget is first shown and whenever it needs to rebuild.
@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("Home")),body: const Center(child: Text("Hello"),),);}
BuildContext is the location of this widget in the tree. You use it to read theme, size, and inherited data:
final color = Theme.of(context).primaryColor;final width = MediaQuery.sizeOf(context).width;
Keep build() simple:
const constructors when the child does not change