Nella precedente lezione abbiamo visto come utilizzare la classe MaterialRoutePage
per lo scambio di dati tra due schermate. In questa lezione ci concentreremo sull'utilizzo di altri due approcci che fanno uso:
- delle rotte nominali;
- della proprietà
MaterialApp.onGenerateRoute
.
Utilizzo delle rotte nominali
Facciamo adesso un passo indietro e torniamo al nostro primo esempio basato sul widget HomePage
e vediamo come utilizzare la proprietà route
.
Analogamente a quanto fatto nella scorsa lezione, definiamo la proprietà MaterialApp.routes
aggiungendo le rotte di interesse come segue.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// . . .
routes: <String, WidgetBuilder>{
'/': (context) => HomePage(),
'/article_details': (context) => ArticleDetailPage(),
},
);
}
}
In questo modo, alla rotta /
corrisponderà la callback
che permetterà al framework di portare l'utente alla HomePage
, mentre con la rotta /article
l'utente verrà redirezionato alla pagina di dettaglio ArticleDetailPage
.
Diversamente da quanto visto negli esempi precedenti, questa volta non abbiamo passato al costruttore della classe ArticleDetailPage
un oggetto Article
. Questo perché le classi devono essere leggermente modificate per poter utilizzare le rotte nominali.
Partiamo dalla classe HomePage
.
L'unica modifica da fare in questa classe riguarda la callback da definire per la proprietà RaisedButton.onPressed
.
onPressed: () {
Article article = new Article('Article', 'This is a simple text for Article');
Navigator.pushNamed(context, '/article_details', arguments: article);
},
In questo caso abbiamo:
- creato un nuovo
Article
; - utilizzato il metodo
Navigator.pushNamed
ma, a differenza di come l'abbiamo utilizzato nella scorsa lezione, questa volta oltre a definire ilBuildContext
e il nome della rotta, abbiamo definito anche il parametroarguments
che offre la possibilità di inoltrare dei dati alla rotta di destinazione.
Non resta quindi che modificare la classe ArticleDetailPage
per accedere all'articolo associato alla proprietà arguments
per poter proseguire.
Diversamente da prima, però, dobbiamo fare un piccola modifica alla nostra classe e trasformarla da StatelessWidget
a StatefulWidget
, in quanto lo stato della classe può cambiare nel tempo ed è necessario definire uno State
che gestisca il cambio delle informazioni secondo le logiche descritte nella lezione 24.
Modifichiamo quindi la classe ArticleDetailPage
affinchè estenda la classe StatefulWidget
e sovrascriva il metodo createState
, che a sua volta invocherà il costruttore della classe _ArticleDetailPageState
. Quest'ultima descriverà lo stato dell'applicazione e sarà responsabile di ricreare il widget qualora ci fossero dei cambiamenti nelle informazioni presentate all'utente.
Riportiamo per semplicità il codice di seguito.
class ArticleDetailPage extends StatefulWidget {
@override
_ArticleDetailPageState createState() => _ArticleDetailPageState();
}
class _ArticleDetailPageState extends State<ArticleDetailPage> {
Article article;
@override
Widget build(BuildContext context) {
RouteSettings settings = ModalRoute.of(context).settings;
article = settings.arguments;
return Scaffold(
appBar: AppBar(
title: Text(article.title),
),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Text(article.description),
),
);
}
}
In particolare, nella classe _ArticleDetailPageState
continuiamo ad avere la proprietà article
(non più final
come nella precedente implementazione), mentre nel metodo build
vengono eseguite le seguenti operazioni:
- accediamo ai
settings
dellaModalRoute
associata alcontext
corrente; - estraiamo dai
settings
il valore associato alla proprietàarguments
; - popoliamo la schermata utilizzando le informazioni estratte e salvate temporaneamente nella proprietà
article
.
Eseguiamo quindi l'applicazione per vedere i risultati delle modifiche effettuate.
Come possiamo vedere, cliccando sul RaisedButton
nella HomePage
, l'utente crea l'article
che viene inoltrato, tramite la rotta nominale, alla nuova pagina dove l'utente visualizza i dettagli dell'articolo.
Utilizzo della proprietà onGenerateRoute
Vediamo infine come lavorare con onGenerateRoute
.
In questo esempio, l'unico punto del codice che dobbiamo modificare è relativo alla classe MyApp
. Infatti dobbiamo aggiungere la proprietà MaterialApp.onGenerateRoute
affinché essa gestisca le due rotte riguardanti la HomePage e l'ArticleDetailPage
, e un default nel caso in cui la rotta scelta non fosse disponibile.
Modifichiamo il codice come segue.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// . . .
onGenerateRoute: (RouteSettings settings) {
switch (settings.name) {
case '/':
return MaterialPageRoute(builder: (context) => HomePageV2());
break;
case '/article_details':
Article article = settings.arguments;
return MaterialPageRoute(
builder: (context) => ArticleDetailPage(article: article),
);
break;
default:
return MaterialPageRoute(builder: (context) => HomePage());
}
},
);
}
}
In questo modo il nostro switch case
prenderà dai settings
le informazioni circa:
- il nome della rotta;
- gli argomenti passati a quella rotta, che in questo caso corrisponderà ad un oggetto di tipo
Article
.
Infatti, quando la rotta corrisponde a /article_details
, il framework estrae l'oggetto Article
passato come argomento per creare la rotta modale, che visualizza il widget ArticleDetailPage
popolato con le informazioni dell'articolo, come mostrato nel precedente esempio.
Eseguendo l'applicazione otterremo lo stesso risultato mostrato nelle figure precedenti. In questo esempio ci siamo limitati a utilizzare la classe MaterialPageRoute
ma, come visto nella lezione precedente, si può usare qualsiasi altro PageRouteBuilder
, come quello visto nella scorsa lezione.
Il codice di questa lezione è disponibile su GitHub.