Flutter Widgets — cosa sono, albero di widget e build

Autore: IT Sectr Pubblicato: 2026-02-21 Tempo di lettura: 8 min

Flutter Widgets — i mattoni fondamentali dell'interfaccia utente nel framework Google Flutter, rilasciato nella versione stabile 1.0 a dicembre 2018. In Flutter, tutto è un widget: da schermi e pulsanti a spaziature e allineamenti. I widget formano un albero (widget tree) che Flutter renderizza sul proprio motore Skia/Impeller, bypassando i componenti nativi della piattaforma. Secondo Google I/O (2025), Flutter è utilizzato in oltre 500.000 app su Google Play e App Store. L'architettura Flutter divide i widget in StatelessWidget (immutabili) e StatefulWidget (con stato mutabile tramite un oggetto State).

Punti Chiave

  • Flutter Widgets — tutti gli elementi UI in Flutter: da schermi e pulsanti a spaziature e allineamenti; il framework non utilizza componenti nativi della piattaforma.
  • StatelessWidget — un widget senza stato mutabile; mostra i dati passati tramite il costruttore e non cambia dopo il build.
  • StatefulWidget — un widget con stato mutabile memorizzato in un oggetto State separato che sopravvive ai rebuild.
  • Albero di widget (widget tree) — una gerarchia di widget che descrive l'UI; Flutter la trasforma in Element Tree e Render Tree per il rendering.
  • BuildContext — il contesto di build che fornisce accesso alla posizione del widget nell'albero, al tema, a MediaQuery e a InheritedWidget.

Cosa sono i Flutter Widgets?

Flutter Widgets — tutti gli elementi UI nel framework Flutter, implementati come classi Dart immutabili. Un widget è la configurazione di un elemento UI: la sua dimensione, colore, posizione e gestori di eventi. A differenza di Android (XML + View) o iOS (Storyboard + UIView), Flutter non usa componenti nativi — tutto viene disegnato dal motore Skia (Android/iOS/Linux) o Impeller (iOS/macOS) su una Canvas. Questo garantisce un aspetto coerente su tutte le piattaforme senza discrepanze di piattaforma. Flutter viene fornito con due insiemi di widget: Material Widgets (Google Material Design 3 per Android/web) e Cupertino Widgets (Apple HIG per iOS/macOS). Lo sviluppatore può combinare entrambi gli insiemi in una singola applicazione. Ogni widget ha un metodo build() che restituisce un widget figlio o una loro composizione — così viene costruito l'albero di widget.

I tre alberi di Flutter

Flutter opera con tre alberi: Widget Tree (configurazione, creata dallo sviluppatore), Element Tree (mappatura del widget alla sua posizione nell'albero, gestita dal framework) e Render Tree (oggetti che calcolano il layout ed eseguono la pittura). Un Widget crea un Element, che crea un RenderObject. L'Element viene riutilizzato quando la configurazione cambia (rebuild) — questo è il meccanismo di ottimizzazione di Flutter: se il tipo di widget e la key corrispondono, l'Element non viene ricreato ma aggiornato con la nuova configurazione. Comprendere i tre alberi è la chiave per ottimizzare le prestazioni delle applicazioni Flutter.

StatelessWidget: widget immutabili

StatelessWidget — un widget che non memorizza stato interno. Riceve parametri tramite il costruttore e li mostra senza possibilità di modifica dopo il build. StatelessWidget è ideale per elementi statici: intestazioni, icone, avatar, elenchi con dati fissi. Il metodo build() viene chiamato una volta alla creazione e quando il widget padre cambia. Poiché StatelessWidget non ha stato, non richiede un oggetto State separato — build() è definito direttamente nella classe del widget.

dart
import 'package:flutter/material.dart';

class ProfileHeader extends StatelessWidget {
  final String name;
  final String avatarUrl;

  const ProfileHeader({super.key, required this.name, required this.avatarUrl});

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        CircleAvatar(
          radius: 24,
          backgroundImage: NetworkImage(avatarUrl),
        ),
        const SizedBox(width: 12),
        Text(
          name,
          style: const TextStyle(
            fontSize: 18,
            fontWeight: FontWeight.bold,
          ),
        ),
      ],
    );
  }
}

ProfileHeader — un StatelessWidget che riceve name e avatarUrl tramite il costruttore. CircleAvatar mostra l'avatar, Text mostra il nome. Il widget non può modificare questi valori dopo la creazione. Usare un costruttore const (const ProfileHeader) permette a Flutter di riutilizzare l'istanza del widget durante il rebuild del padre — una micro-ottimizzazione raccomandata per tutti i StatelessWidget.

StatefulWidget: widget con stato

StatefulWidget — un widget con stato mutabile memorizzato in un oggetto State separato. Lo StatefulWidget stesso è immutabile, come StatelessWidget. La parte mutabile è delegata a State: State è un oggetto creato una volta che sopravvive a molteplici rebuild del widget. Quando lo stato cambia (setState()), Flutter chiama build() su State, aggiornando l'UI. StatefulWidget è usato per elementi interattivi: contatori, campi di testo, checkbox, animazioni, timer.

dart
import 'package:flutter/material.dart';

class LikeButton extends StatefulWidget {
  const LikeButton({super.key});

  @override
  State<LikeButton> createState() => _LikeButtonState();
}

class _LikeButtonState extends State<LikeButton> {
  bool liked = false;
  int count = 42;

  void _toggleLike() {
    setState(() {
      liked = !liked;
      count += liked ? 1 : -1;
    });
  }

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: _toggleLike,
      child: Text(liked ? '♥ $count' : '♡ $count'),
    );
  }
}

LikeButton — un StatefulWidget con la classe State _LikeButtonState. I campi liked e count sono lo stato memorizzato in State e non vengono resettati al rebuild. setState() notifica a Flutter che l'UI deve essere ricostruita. Flutter non ricrea State ad ogni rebuild del padre — solo quando la configurazione cambia (key o tipo di widget). In IT Sectr, usiamo StatelessWidget per la visualizzazione e StatefulWidget per i componenti interattivi, seguendo il principio di minimizzare StatefulWidget fino ai confini della mutazione.

Albero di widget: da Widget a RenderObject

Widget Tree — una struttura gerarchica di widget che descrive l'UI dell'applicazione. Flutter converte il Widget Tree in Element Tree: ogni Widget crea un Element, che traccia la sua posizione nell'albero e la sua connessione a un RenderObject. Il Render Tree esegue il layout (determinazione di dimensioni e posizioni) e la pittura (rendering). L'Element è un livello di ottimizzazione chiave: se il tipo di widget e la key non sono cambiati durante un rebuild, l'Element viene riutilizzato, aggiornando la configurazione senza ricreare il RenderObject. Questo garantisce le prestazioni di Flutter a frame rate elevati (60/120 FPS).

dart
import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Widget Flutter')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Icon(Icons.flutter_dash, size: 80),
            const SizedBox(height: 16),
            const Text(
              'Ciao, Flutter!',
              style: TextStyle(fontSize: 24),
            ),
          ],
        ),
      ),
    );
  }
}

Albero di widget HomeScreen: Scaffold → AppBar + Center → Column → [Icon, SizedBox, Text]. Scaffold è il widget radice di layout di Material Design. Center centra la sua Column figlia. Column dispone i figli verticalmente con allineamento centrato (mainAxisAlignment.center). Flutter calcola il layout dall'alto verso il basso (i vincoli sono passati dal padre) e le dimensioni dal basso verso l'alto (sizedByParent o dimensionamento dai figli).

BuildContext: contesto di build e accesso all'albero

BuildContext — un descrittore della posizione del widget nell'Element Tree. Ogni metodo build() riceve un BuildContext, attraverso il quale il widget può accedere a: MediaQuery (dimensioni dello schermo, orientamento, densità di pixel, area sicura), Theme (MaterialThemeData o CupertinoThemeData), Navigator (pila di navigazione), ScaffoldMessenger (SnackBar), InheritedWidget (passaggio di dati verso il basso nell'albero). BuildContext non deve essere salvato dopo il completamento di build() o usato al di fuori di un contesto sincrono — questo causa errori come “Scaffold.of() called with a context that does not contain a Scaffold”. Invece di salvare il context, usa il widget Builder o il pattern InheritedWidget per accedere ai dati.

Key: identificazione del widget nell'albero

Key — un parametro opzionale del costruttore di ogni widget (super.key). Key aiuta Flutter a identificare un widget quando l'ordine o il numero di elementi in una lista cambia. Senza key, Flutter confronta i widget per tipo e posizione; quando si aggiunge un elemento in mezzo a una lista senza key, Flutter riutilizza l'Element per il widget sbagliato, causando bug di stato (StatefulWidget) e problemi di animazione. Usa ValueKey (identificatore univoco) per le liste, ObjectKey (basato sull'oggetto dati), UniqueKey (garantito univoco ad ogni rebuild — per ricreazione forzata).

Catalogo widget Flutter: Material, Cupertino, Layout

Flutter SDK (versione stabile 3.3+, Dart 3+) include oltre 200 widget integrati divisi in categorie: Layout (Row, Column, Stack, Container, Expanded, Flexible, Wrap, GridView, ListView, CustomScrollView), Material Design (Scaffold, AppBar, Card, Drawer, BottomNavigationBar, FloatingActionButton, TabBar, Chip, DataTable), Cupertino (CupertinoPageScaffold, CupertinoNavigationBar, CupertinoButton, CupertinoTabBar), Painting & Effects (Opacity, DecoratedBox, ClipRect, Transform, BackdropFilter, ShaderMask), Async (FutureBuilder, StreamBuilder) e Accessibility (Semantics, MergeSemantics, ExcludeSemantics). I widget di layout sono la base di qualsiasi UI Flutter: Row per sequenze orizzontali, Column per verticali, Stack per elementi sovrapposti, Container con BoxDecoration per decorazione.

CategoriaWidget chiaveScopo
LayoutRow, Column, Stack, Container, Expanded, FlexiblePosizionamento e dimensionamento dei figli
MaterialScaffold, AppBar, Card, Drawer, FAB, TabBarComponenti UI Material Design 3
CupertinoCupertinoPageScaffold, CupertinoNavigationBar, CupertinoButtonComponenti in stile iOS
PaintingOpacity, ClipRect, Transform, DecoratedBox, BackdropFilterEffetti visivi e clipping
AsyncFutureBuilder, StreamBuilderCaricamento dati asincrono con stati UI
AccessibilitySemantics, MergeSemanticsMarkup semantico per screen reader

Domande Frequenti

In cosa differisce StatelessWidget da StatefulWidget?

StatelessWidget non ha stato interno — tutti i dati sono passati tramite il costruttore e non cambiano. StatefulWidget memorizza lo stato mutabile in un oggetto State separato che sopravvive ai rebuild. Il cambiamento di stato chiama setState(), e Flutter ricostruisce l'UI. Usa StatelessWidget per elementi immutabili; usa StatefulWidget per elementi interattivi.

Cos'è BuildContext in Flutter?

BuildContext è un descrittore della posizione del widget nell'Element Tree, passato al metodo build(). Attraverso il context, un widget accede a MediaQuery, Theme, Navigator, ScaffoldMessenger e InheritedWidget. BuildContext non deve essere salvato dopo il completamento di build(). Per accedere ai dati, usa il widget Builder o InheritedWidget.

È necessario conoscere Dart per lavorare con Flutter?

Sì, Flutter usa Dart come unico linguaggio di programmazione. Dart è un linguaggio tipizzato staticamente con null safety, sound null safety, extension methods e pattern matching. Per iniziare, sono sufficienti le basi di Dart: classi, funzioni, async/await, collezioni. Dart viene compilato in codice nativo (AOT) tramite Dart Native e in JavaScript (per il web) tramite Dart2JS.

Flutter è solo per piattaforme mobili?

No, Flutter supporta sei piattaforme: iOS, Android, Web, macOS, Windows, Linux. Oltre il 90% del codice è condiviso tra tutte le piattaforme. Gli adattamenti di piattaforma (fotocamera, filesystem) sono implementati tramite plugin o platform channels. Per il desktop, Flutter utilizza la shell finestra Flutter Desktop; per il web, utilizza il motore CanvasKit (WebGL) o il renderer HTML.

Come fa Flutter a raggiungere prestazioni di 60 FPS?

Flutter raggiunge 60/120 FPS grazie a: motore 2D proprietario (Skia/Impeller), assenza di bridge nativo (a differenza di React Native), tre alberi (Widget → Element → Render) con riutilizzo di Element quando tipo/key rimangono invariati, un algoritmo di layout a passaggio unidirezionale (vincoli verso il basso, dimensioni verso l'alto) e RepaintBoundary per isolare il ripainting di singole aree dello schermo.

Riepilogo

  • Flutter Widgets — tutti gli elementi UI: da Scaffold a SizedBox; Flutter li renderizza da solo su Skia/Impeller, senza usare componenti nativi.
  • StatelessWidget — un widget senza stato; build() restituisce l'UI basata su parametri del costruttore immutabili.
  • StatefulWidget — un widget con stato mutabile in State; setState() attiva il rebuild dell'UI.
  • Tre alberi Flutter: Widget (configurazione) → Element (posizione) → Render (layout + pittura); Element è riutilizzato per prestazioni.
  • BuildContext — la posizione del widget nell'albero; accesso a MediaQuery, Theme, Navigator, InheritedWidget.
  • Material e Cupertino — due insiemi di widget rispettivamente per Google Material Design 3 e Apple HIG.
  • Key (ValueKey, ObjectKey, UniqueKey) — identificazione del widget al cambiamento di ordine o quantità in una lista.

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche