La navigazione è uno dei punti più sottovalutati in Flutter.
All’inizio sembra semplice, ma cresce insieme alla complessità dell’app.
In questa Lezione 4 affrontiamo la navigazione partendo dalle basi corrette, senza scorciatoie, per evitare problemi strutturali quando il progetto cresce.
Il modello mentale: la navigazione è uno stack
Flutter gestisce la navigazione tramite uno stack di pagine.
Immagina una pila:
- la schermata attuale è in cima
- quando fai
push, aggiungi una pagina - quando fai
pop, torni indietro
Questo modello è fondamentale per capire perché certe cose funzionano e altre no.
Il Navigator: come funziona davvero
Il cuore della navigazione in Flutter è il widget Navigator.
Esempio base:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailPage(),
),
);
Questo codice:
- crea una nuova route
- la mette in cima allo stack
- mostra la nuova schermata
Per tornare indietro:
Navigator.pop(context);
Semplice, ma non banale:
stai modificando lo stack, non “cambiando schermata”.
Perché BuildContext è importante
Il BuildContext non è un dettaglio.
È il collegamento tra:
- widget
- albero dei widget
- navigator corretto
Usare il context sbagliato può causare:
- crash
- navigazione che non funziona
- comportamenti imprevedibili
Regola pratica:
usa sempre il
BuildContextpiù vicino possibile al widget che deve navigare.
Passare dati tra schermate
Uno dei problemi più comuni è passare dati in modo scorretto.
Approccio corretto:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailPage(id: itemId),
),
);
E nella schermata di destinazione:
class DetailPage extends StatelessWidget {
final int id;
const DetailPage({required this.id});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Dettaglio $id')),
body: ...
);
}
}
Questo mantiene:
- dipendenze chiare
- costruttori espliciti
- codice leggibile
Restituire dati con pop
Flutter permette anche di ritornare dati da una schermata:
final result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SelectionPage(),
),
);
print(result);
Nella schermata chiamata:
Navigator.pop(context, selectedValue);
Questo è fondamentale per:
- form
- selezioni
- flussi guidati
Rotte nominate: quando servono
Le named routes permettono di separare:
- definizione delle schermate
- utilizzo della navigazione
Esempio:
MaterialApp(
routes: {
'/': (context) => HomePage(),
'/details': (context) => DetailsPage(),
},
);
Navigazione:
Navigator.pushNamed(context, '/details');
Questo approccio migliora:
- leggibilità
- organizzazione
- testabilità
Ma non è sempre la scelta migliore per app complesse.
Per questo non ci fermiamo qui.
Errori comuni da evitare
Nella lezione insistiamo molto su questi errori:
❌ Navigare dentro la logica di business
❌ Mescolare UI e flussi
❌ Passare BuildContext in giro
❌ Navigare durante un build()
❌ Gestire la navigazione come “side effect”
Questi errori diventano incubi nei progetti reali.
Perché questa lezione è una base, non un punto di arrivo
Questa lezione non introduce GoRouter.
Ed è una scelta intenzionale.
Senza capire:
- stack
- context
- push/pop
- flussi base
GoRouter diventa:
“una cosa che funziona… finché non smette di funzionare”.
La Lezione 4 costruisce le fondamenta corrette per la Lezione 5, dove affronteremo la navigazione avanzata.
Il corso Flutter gratuito su YouTube
Questa lezione fa parte di un corso Flutter che stiamo pubblicando gratuitamente su YouTube.
Caratteristiche:
- registrazioni reali di un corso live
- una lezione = un video completo
- una nuova lezione ogni settimana
? Playlist completa del corso Flutter
Conclusione
La navigazione non è un dettaglio visivo.
È una parte strutturale dell’app.
Capirla ora significa:
→ meno bug
→ codice più pulito
→ meno refactor
→ progetti più solidi
Nel prossimo articolo entreremo nella navigazione avanzata con GoRouter.

