Everything in Flutter is a widget. Composition over inheritance. StatelessWidget for static UI, StatefulWidget for mutable state.

StatelessWidget

  class Greeting extends StatelessWidget {
  final String name;
  const Greeting({super.key, required this.name});

  @override
  Widget build(BuildContext context) {
    return Text('Hello, $name!');
  }
}
  

StatefulWidget

  class Counter extends StatefulWidget {
  const Counter({super.key});
  @override
  State<Counter> createState() => _CounterState();
}

class _CounterState extends State<Counter> {
  int count = 0;
  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () => setState(() => count++),
      child: Text('Count: $count'),
    );
  }
}
  

Layout Widgets

  Column(
  children: [
    Row(children: [Icon(Icons.star), Text('Rating')]),
    Expanded(child: ListView(...)),
    Padding(padding: EdgeInsets.all(16), child: ...),
  ],
)
  

Container and Box

  Container(
  padding: EdgeInsets.all(16),
  margin: EdgeInsets.symmetric(horizontal: 8),
  decoration: BoxDecoration(
    color: Colors.blue,
    borderRadius: BorderRadius.circular(8),
  ),
  child: Text('Styled'),
)
  

Scaffold

  Scaffold(
  appBar: AppBar(title: Text('My App')),
  body: Center(child: Text('Content')),
  floatingActionButton: FloatingActionButton(onPressed: () {}),
)
  

Common Pitfalls

  • Ignoring null safety warnings and using ! operator carelessly.
  • Calling setState excessively causing unnecessary rebuilds.
  • Mixing async patterns without proper error handling.
  • Hardcoding values that should be theme constants.

Best Practices

  • Prefer const constructors for static widgets.
  • Use named parameters for widget constructors.
  • Extract reusable widgets into separate files.
  • Write widget tests for critical UI paths.

Memory and Performance Notes

Deep widget trees increase build cost. Extract subtrees into separate widgets.

Exercise

Build a profile card with avatar, name, bio using Column, Row, Container, and CircleAvatar.

Hint: Use const constructors wherever possible to avoid rebuilds.

Summary

Practice with Flutter DevTools open to observe rebuilds and performance.

Debugging Checklist

  1. Read the full error in the console.
  2. Use Flutter DevTools widget inspector.
  3. Hot restart vs hot reload — know the difference.
  4. Check null safety and type errors first.
  5. Simplify widget tree to isolate the issue.

Real-World Application

Production Flutter apps combine these patterns with analytics, crash reporting, and CI/CD.

Further Reading

Flutter documentation, Dart language tour, and pub.dev packages.

Additional Examples

Consider how this topic applies in a larger project:

  // Break the problem into smaller functions
// Test each function independently
// Integrate incrementally
  

Working through variations of the examples above builds deeper understanding than reading alone.