[{"data":1,"prerenderedAt":75},["ShallowReactive",2],{"tutorial-navigazione-tra-schermate-in-flutter-con-go-router":3,"comments-tutorial-navigazione-tra-schermate-in-flutter-con-go-router":74},{"id":4,"title":5,"slug":6,"excerpt":7,"intro":8,"cover_image":9,"video_url":10,"difficulty":11,"estimated_minutes":12,"flutter_version":13,"status":14,"published_at":15,"meta_title":16,"meta_description":17,"category":18,"author":22,"steps":24},3,"Navigazione tra schermate in Flutter con go_router","navigazione-tra-schermate-in-flutter-con-go-router","Impara a gestire la navigazione dichiarativa in Flutter usando go_router: rotte, parametri, redirect e gestione degli errori in modo semplice e scalabile.","La navigazione è uno degli aspetti fondamentali di ogni applicazione mobile. Flutter offre il `Navigator` integrato, ma quando l'app cresce gestire le rotte in modo imperativo diventa complicato.\n\nIn questo tutorial useremo **go_router**, il pacchetto ufficiale supportato dal team Flutter, che permette una navigazione **dichiarativa** basata su URL. Vedremo come definire le rotte, passare parametri, gestire i redirect (utili per l'autenticazione) e configurare una pagina di errore.\n\nAl termine avrai una struttura di navigazione pulita e pronta per scalare.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Ftutorials\u002Fbae7fb51-7bc4-426c-a353-9f83508b231e.jpg",null,"intermediate",35,"3.x","published","2026-06-09T06:23:44+00:00","Navigazione in Flutter con go_router: guida pratica","Tutorial su go_router in Flutter: definisci rotte dichiarative, passa parametri, gestisci redirect e errori in modo scalabile.",{"id":19,"name":20,"slug":21},1,"Guide","guide",{"id":19,"name":23},"Flutter Bot",[25,32,40,46,53,60,67],{"id":26,"position":19,"title":27,"body":28,"code_snippet":29,"code_language":30,"expected_result":31,"demo_url":10,"video_url":10},25,"Aggiungere la dipendenza go_router","Per prima cosa aggiungiamo il pacchetto `go_router` al nostro progetto. Apri il file `pubspec.yaml` e inserisci la dipendenza nella sezione `dependencies`.\n\nIn alternativa puoi eseguire il comando da terminale:\n\n```bash\nflutter pub add go_router\n```\n\nDopo l'aggiunta esegui `flutter pub get` per scaricare il pacchetto.","dependencies:\n  flutter:\n    sdk: flutter\n  go_router: ^14.0.0","yaml","Il pacchetto go_router è installato e disponibile per l'import nel progetto.",{"id":33,"position":34,"title":35,"body":36,"code_snippet":37,"code_language":38,"expected_result":39,"demo_url":10,"video_url":10},26,2,"Creare le schermate di base","Creiamo due semplici schermate che useremo per la navigazione: una **HomeScreen** e una **DetailsScreen**. La schermata dei dettagli accetterà un parametro `id` che mostreremo a video.\n\nQueste sono normali `StatelessWidget` di Flutter.","import 'package:flutter\u002Fmaterial.dart';\nimport 'package:go_router\u002Fgo_router.dart';\n\nclass HomeScreen extends StatelessWidget {\n  const HomeScreen({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(title: const Text('Home')),\n      body: Center(\n        child: ElevatedButton(\n          onPressed: () => context.go('\u002Fdetails\u002F42'),\n          child: const Text('Vai ai dettagli'),\n        ),\n      ),\n    );\n  }\n}\n\nclass DetailsScreen extends StatelessWidget {\n  final String id;\n  const DetailsScreen({super.key, required this.id});\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(title: const Text('Dettagli')),\n      body: Center(child: Text('Elemento con id: $id')),\n    );\n  }\n}","dart","Hai due widget pronti: HomeScreen con un bottone e DetailsScreen che riceve un id.",{"id":41,"position":4,"title":42,"body":43,"code_snippet":44,"code_language":38,"expected_result":45,"demo_url":10,"video_url":10},27,"Configurare il GoRouter","Definiamo ora la configurazione delle rotte. Creiamo un'istanza di `GoRouter` con la lista delle `GoRoute`.\n\nNota l'uso di `:id` nel path: è un **parametro dinamico** che recuperiamo tramite `state.pathParameters`.","final GoRouter router = GoRouter(\n  initialLocation: '\u002F',\n  routes: [\n    GoRoute(\n      path: '\u002F',\n      builder: (context, state) => const HomeScreen(),\n    ),\n    GoRoute(\n      path: '\u002Fdetails\u002F:id',\n      builder: (context, state) {\n        final id = state.pathParameters['id']!;\n        return DetailsScreen(id: id);\n      },\n    ),\n  ],\n);","Hai un oggetto router con due rotte: la home e i dettagli con parametro id.",{"id":47,"position":48,"title":49,"body":50,"code_snippet":51,"code_language":38,"expected_result":52,"demo_url":10,"video_url":10},28,4,"Collegare il router all'app","Per attivare go_router dobbiamo usare il costruttore `MaterialApp.router` al posto del classico `MaterialApp`, passando la configurazione tramite `routerConfig`.","import 'package:flutter\u002Fmaterial.dart';\nimport 'package:go_router\u002Fgo_router.dart';\n\nvoid main() => runApp(const MyApp());\n\nclass MyApp extends StatelessWidget {\n  const MyApp({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp.router(\n      title: 'Demo go_router',\n      routerConfig: router,\n    );\n  }\n}","Avviando l'app vedi la HomeScreen; toccando il bottone navighi a \u002Fdetails\u002F42.",{"id":54,"position":55,"title":56,"body":57,"code_snippet":58,"code_language":38,"expected_result":59,"demo_url":10,"video_url":10},29,5,"Aggiungere named routes e parametri query","Usare i path completi nel codice è poco manutenibile. go_router permette di assegnare un **nome** alle rotte e navigare con `goNamed`. Possiamo anche passare parametri query.\n\nAggiorniamo la rotta dei dettagli con un nome e leggiamo un eventuale parametro query `from`.","GoRoute(\n  path: '\u002Fdetails\u002F:id',\n  name: 'details',\n  builder: (context, state) {\n    final id = state.pathParameters['id']!;\n    final from = state.uri.queryParameters['from'] ?? 'sconosciuto';\n    return DetailsScreen(id: id, from: from);\n  },\n),\n\n\u002F\u002F Navigazione con nome e parametri:\ncontext.goNamed(\n  'details',\n  pathParameters: {'id': '42'},\n  queryParameters: {'from': 'home'},\n);","Puoi navigare usando il nome della rotta e leggere i parametri query come 'from'.",{"id":61,"position":62,"title":63,"body":64,"code_snippet":65,"code_language":38,"expected_result":66,"demo_url":10,"video_url":10},30,6,"Gestire i redirect per l'autenticazione","Una funzionalità potente di go_router è il `redirect`, eseguito prima di mostrare una rotta. È perfetto per proteggere pagine riservate agli utenti autenticati.\n\nSe l'utente non è loggato e tenta di accedere a una rotta protetta, lo reindirizziamo alla pagina di login.","bool isLoggedIn = false;\n\nfinal router = GoRouter(\n  initialLocation: '\u002F',\n  redirect: (context, state) {\n    final goingToProfile = state.matchedLocation == '\u002Fprofile';\n    if (goingToProfile && !isLoggedIn) {\n      return '\u002Flogin';\n    }\n    return null; \u002F\u002F nessun redirect\n  },\n  routes: [\n    GoRoute(path: '\u002F', builder: (c, s) => const HomeScreen()),\n    GoRoute(path: '\u002Flogin', builder: (c, s) => const LoginScreen()),\n    GoRoute(path: '\u002Fprofile', builder: (c, s) => const ProfileScreen()),\n  ],\n);","Tentando di aprire \u002Fprofile senza login, vieni reindirizzato a \u002Flogin.",{"id":68,"position":69,"title":70,"body":71,"code_snippet":72,"code_language":38,"expected_result":73,"demo_url":10,"video_url":10},31,7,"Aggiungere una pagina di errore personalizzata","Infine, gestiamo le rotte non valide con `errorBuilder`. Quando l'utente naviga verso un URL inesistente, mostriamo una schermata di errore amichevole con un pulsante per tornare alla home.","final router = GoRouter(\n  initialLocation: '\u002F',\n  errorBuilder: (context, state) => Scaffold(\n    appBar: AppBar(title: const Text('Errore')),\n    body: Center(\n      child: Column(\n        mainAxisSize: MainAxisSize.min,\n        children: [\n          Text('Pagina non trovata: ${state.uri}'),\n          const SizedBox(height: 16),\n          ElevatedButton(\n            onPressed: () => context.go('\u002F'),\n            child: const Text('Torna alla Home'),\n          ),\n        ],\n      ),\n    ),\n  ),\n  routes: [\n    GoRoute(path: '\u002F', builder: (c, s) => const HomeScreen()),\n  ],\n);","Navigando verso una rotta inesistente vedi la pagina di errore con il pulsante per tornare alla home.",[],1781247857912]