Router
Introduzione
Le rotte ti permettono di definire le diverse pagine nella tua app e navigare tra di esse.
Usa le rotte quando hai bisogno di:
- Definire le pagine disponibili nella tua app
- Navigare gli utenti tra le schermate
- Proteggere le pagine dietro l'autenticazione
- Passare dati da una pagina all'altra
- Gestire i deep link dagli URL
Puoi aggiungere rotte all'interno del file lib/routes/router.dart.
appRouter() => nyRoutes((router) {
router.add(HomePage.path).initialRoute();
router.add(PostsPage.path);
router.add(PostDetailPage.path);
// add more routes
// router.add(AccountPage.path);
});
Suggerimento: Puoi creare le tue rotte manualmente o utilizzare lo strumento CLI Metro per crearle automaticamente.
Ecco un esempio di creazione di una pagina 'account' utilizzando Metro.
metro make:page account_page
// Adds your new route automatically to /lib/routes/router.dart
appRouter() => nyRoutes((router) {
...
router.add(AccountPage.path);
});
Potresti anche aver bisogno di passare dati da una vista all'altra. In Nylo Website, questo e possibile utilizzando NyStatefulWidget (un widget con stato che integra l'accesso ai dati di rotta). Approfondiremo questo argomento per spiegare come funziona.
Aggiungere rotte
Questo e il modo piu semplice per aggiungere nuove rotte al tuo progetto.
Esegui il comando seguente per creare una nuova pagina.
metro make:page profile_page
Dopo aver eseguito il comando sopra, verra creato un nuovo Widget chiamato ProfilePage e aggiunto alla directory resources/pages/.
Verra anche aggiunta la nuova rotta al file lib/routes/router.dart.
File: /lib/routes/router.dart
appRouter() => nyRoutes((router) {
...
router.add(HomePage.path).initialRoute();
// My new route
router.add(ProfilePage.path);
});
Navigare verso le pagine
Puoi navigare verso nuove pagine utilizzando l'helper routeTo.
void _pressedSettings() {
routeTo(SettingsPage.path);
}
Rotta iniziale
Nei tuoi router, puoi definire la prima pagina che deve caricarsi utilizzando il metodo .initialRoute().
Una volta impostata la rotta iniziale, sara la prima pagina che si carica quando apri l'app.
appRouter() => nyRoutes((router) {
router.add(HomePage.path);
router.add(SettingsPage.path);
router.add(ProfilePage.path).initialRoute();
// new initial route
});
Rotta Iniziale Condizionale
Puoi anche impostare una rotta iniziale condizionale utilizzando il parametro when:
appRouter() => nyRoutes((router) {
router.add(OnboardingPage.path).initialRoute(
when: () => !hasCompletedOnboarding()
);
router.add(HomePage.path).initialRoute(
when: () => hasCompletedOnboarding()
);
});
Navigare alla Rotta Iniziale
Usa routeToInitial() per navigare alla rotta iniziale dell'app:
void _goHome() {
routeToInitial();
}
Questo navighera alla rotta contrassegnata con .initialRoute() e cancellera lo stack di navigazione.
Rotta di Anteprima
Durante lo sviluppo, potresti voler visualizzare rapidamente una pagina specifica senza cambiare permanentemente la tua rotta iniziale. Usa .previewRoute() per rendere temporaneamente qualsiasi rotta la rotta iniziale:
appRouter() => nyRoutes((router) {
router.add(HomePage.path).initialRoute();
router.add(SettingsPage.path);
router.add(ProfilePage.path).previewRoute(); // This will be shown first during development
});
Il metodo previewRoute():
- Sovrascrive qualsiasi impostazione esistente di
initialRoute()eauthenticatedRoute() - Rende la rotta specificata la rotta iniziale
- Utile per testare rapidamente pagine specifiche durante lo sviluppo
Attenzione: Ricorda di rimuovere
.previewRoute()prima di rilasciare la tua app!
Rotta Autenticata
Nella tua app, puoi definire una rotta come rotta iniziale quando un utente e autenticato. Questo sovrascrivera automaticamente la rotta iniziale predefinita e sara la prima pagina che l'utente vede quando effettua il login.
Per prima cosa, il tuo utente dovrebbe essere autenticato utilizzando l'helper Auth.authenticate({...}).
Ora, quando aprono l'app, la rotta che hai definito sara la pagina predefinita fino a quando non effettuano il logout.
appRouter() => nyRoutes((router) {
router.add(IntroPage.path).initialRoute();
router.add(LoginPage.path);
router.add(ProfilePage.path).authenticatedRoute();
// auth page
});
Rotta Autenticata Condizionale
Puoi anche impostare una rotta autenticata condizionale:
router.add(ProfilePage.path).authenticatedRoute(
when: () => hasCompletedSetup()
);
Navigare alla Rotta Autenticata
Puoi navigare alla pagina autenticata utilizzando l'helper routeToAuthenticatedRoute():
routeToAuthenticatedRoute();
Vedi anche: Autenticazione per i dettagli sull'autenticazione degli utenti e la gestione delle sessioni.
Rotta Sconosciuta
Puoi definire una rotta per gestire scenari 404/non trovato utilizzando .unknownRoute():
appRouter() => nyRoutes((router) {
router.add(HomePage.path).initialRoute();
router.add(NotFoundPage.path).unknownRoute();
});
Quando un utente naviga verso una rotta che non esiste, verra mostrata la pagina della rotta sconosciuta.
Route guard
I route guard proteggono le pagine da accessi non autorizzati. Si eseguono prima che la navigazione venga completata, permettendoti di reindirizzare gli utenti o bloccare l'accesso in base a condizioni.
Usa i route guard quando hai bisogno di:
- Proteggere le pagine da utenti non autenticati
- Verificare le autorizzazioni prima di consentire l'accesso
- Reindirizzare gli utenti in base a condizioni (es. onboarding non completato)
- Registrare o tracciare le visualizzazioni di pagina
Per creare un nuovo Route Guard, esegui il comando seguente.
metro make:route_guard dashboard
Successivamente, aggiungi il nuovo Route Guard alla tua rotta.
// File: /routes/router.dart
appRouter() => nyRoutes((router) {
router.add(HomePage.path);
router.add(LoginPage.path);
router.add(DashboardPage.path,
routeGuards: [
DashboardRouteGuard() // Add your guard
]
); // restricted page
});
Puoi anche impostare route guard utilizzando il metodo addRouteGuard:
// File: /routes/router.dart
appRouter() => nyRoutes((router) {
router.add(DashboardPage.path)
.addRouteGuard(MyRouteGuard());
// or add multiple guards
router.add(DashboardPage.path)
.addRouteGuards([MyRouteGuard(), MyOtherRouteGuard()]);
})
Ciclo di Vita NyRouteGuard
Nella v7, i route guard utilizzano la classe NyRouteGuard con tre metodi del ciclo di vita:
onBefore(RouteContext context)- Chiamato prima della navigazione. Restituiscenext()per continuare,redirect()per andare altrove, oabort()per fermarsi.onAfter(RouteContext context)- Chiamato dopo la navigazione riuscita verso la rotta.
Esempio Base
File: /routes/guards/dashboard_route_guard.dart
class DashboardRouteGuard extends NyRouteGuard {
DashboardRouteGuard();
@override
Future<GuardResult> onBefore(RouteContext context) async {
// Perform a check if they can access the page
bool userLoggedIn = await Auth.isAuthenticated();
if (userLoggedIn == false) {
return redirect(LoginPage.path);
}
return next();
}
@override
Future<void> onAfter(RouteContext context) async {
// Track page view after successful navigation
Analytics.trackPageView(context.routeName);
}
}
RouteContext
La classe RouteContext fornisce accesso alle informazioni di navigazione:
| Proprieta | Tipo | Descrizione |
|---|---|---|
context |
BuildContext? |
Contesto di build corrente |
data |
dynamic |
Dati passati alla rotta |
queryParameters |
Map<String, String> |
Parametri query dell'URL |
routeName |
String |
Nome/percorso della rotta |
originalRouteName |
String? |
Nome originale della rotta prima delle trasformazioni |
@override
Future<GuardResult> onBefore(RouteContext context) async {
print('Navigating to: ${context.routeName}');
print('Query params: ${context.queryParameters}');
print('Route data: ${context.data}');
return next();
}
Metodi Helper dei Guard
next()
Prosegui verso il guard successivo o verso la rotta:
@override
Future<GuardResult> onBefore(RouteContext context) async {
return next(); // Allow navigation to continue
}
redirect()
Reindirizza verso una rotta diversa:
@override
Future<GuardResult> onBefore(RouteContext context) async {
if (!isLoggedIn) {
return redirect(
LoginPage.path,
data: {'returnTo': context.routeName},
navigationType: NavigationType.pushReplace,
);
}
return next();
}
Il metodo redirect() accetta:
| Parametro | Tipo | Descrizione |
|---|---|---|
path |
Object |
Percorso della rotta o RouteView |
data |
dynamic |
Dati da passare alla rotta |
queryParameters |
Map<String, dynamic>? |
Parametri query |
navigationType |
NavigationType |
Tipo di navigazione (predefinito: pushReplace) |
transitionType |
TransitionType? |
Transizione di pagina |
onPop |
Function(dynamic)? |
Callback quando la rotta viene rimossa |
abort()
Ferma la navigazione senza reindirizzare:
@override
Future<GuardResult> onBefore(RouteContext context) async {
if (isMaintenanceMode) {
showMaintenanceDialog();
return abort(); // User stays on current route
}
return next();
}
setData()
Modifica i dati passati ai guard successivi e alla rotta:
@override
Future<GuardResult> onBefore(RouteContext context) async {
final user = await fetchUser();
setData({'user': user, ...?context.data});
return next();
}
Guard Parametrizzati
Usa ParameterizedGuard quando hai bisogno di configurare il comportamento del guard per ogni rotta:
class RoleGuard extends ParameterizedGuard<List<String>> {
RoleGuard(super.params);
@override
Future<GuardResult> onBefore(RouteContext context) async {
final user = await Auth.user();
if (!params.any((role) => user.hasRole(role))) {
return redirect('/unauthorized');
}
return next();
}
}
// Usage:
router.add(AdminPage.path, routeGuards: [
RoleGuard(['admin', 'moderator'])
]);
Stack di Guard
Componi piu guard in un singolo guard riutilizzabile utilizzando GuardStack:
// Create reusable guard combinations
final adminGuards = GuardStack([
AuthGuard(),
RoleGuard(['admin']),
AuditLogGuard(),
]);
router.add(AdminPage.path, routeGuards: [adminGuards]);
Guard Condizionali
Applica guard condizionalmente basandoti su un predicato:
router.add(DashboardPage.path, routeGuards: [
ConditionalGuard(
condition: (context) => context.routeName.startsWith('/admin'),
guard: AdminGuard(),
)
]);
Passaggio di dati a un'altra pagina
In questa sezione, mostreremo come puoi passare dati da un widget all'altro.
Dal tuo Widget, usa l'helper routeTo e passa i data che vuoi inviare alla nuova pagina.
// HomePage Widget
void _pressedSettings() {
routeTo(SettingsPage.path, data: "Hello World");
}
...
// SettingsPage Widget (other page)
class _SettingsPageState extends NyPage<SettingsPage> {
...
@override
get init => () {
print(widget.data()); // Hello World
// or
print(data()); // Hello World
};
Altri esempi
// Home page widget
class _HomePageState extends NyPage<HomePage> {
_showProfile() {
User user = new User();
user.firstName = 'Anthony';
routeTo(ProfilePage.path, data: user);
}
...
// Profile page widget (other page)
class _ProfilePageState extends NyPage<ProfilePage> {
@override
get init => () {
User user = widget.data();
print(user.firstName); // Anthony
};
Gruppi di Rotte
I gruppi di rotte organizzano le rotte correlate e applicano impostazioni condivise. Sono utili quando piu rotte necessitano degli stessi guard, prefisso URL o stile di transizione.
Usa i gruppi di rotte quando hai bisogno di:
- Applicare lo stesso route guard a piu pagine
- Aggiungere un prefisso URL a un insieme di rotte (es.
/admin/...) - Impostare la stessa transizione di pagina per rotte correlate
Puoi definire un gruppo di rotte come nell'esempio seguente.
appRouter() => nyRoutes((router) {
...
router.group(() => {
"route_guards": [AuthRouteGuard()],
"prefix": "/dashboard",
"transition_type": TransitionType.fade(),
}, (router) {
router.add(ChatPage.path);
router.add(FollowersPage.path);
});
Impostazioni opzionali per i gruppi di rotte sono:
| Impostazione | Tipo | Descrizione |
|---|---|---|
route_guards |
List<RouteGuard> |
Applica route guard a tutte le rotte del gruppo |
prefix |
String |
Aggiunge un prefisso a tutti i percorsi delle rotte del gruppo |
transition_type |
TransitionType |
Imposta la transizione per tutte le rotte del gruppo |
transition |
PageTransitionType |
Imposta il tipo di transizione della pagina (deprecato, usa transition_type) |
transition_settings |
PageTransitionSettings |
Imposta le impostazioni di transizione |
Utilizzo dei Parametri delle Rotte
Quando crei una nuova pagina, puoi aggiornare la rotta per accettare parametri.
class ProfilePage extends NyStatefulWidget<HomeController> {
static RouteView path = ("/profile/{userId}", (_) => ProfilePage());
ProfilePage() : super(child: () => _ProfilePageState());
}
Ora, quando navighi verso la pagina, puoi passare l'userId
routeTo(ProfilePage.path.withParams({"userId": 7}));
Puoi accedere ai parametri nella nuova pagina in questo modo.
class _ProfilePageState extends NyPage<ProfilePage> {
@override
get init => () {
print(widget.queryParameters()); // {"userId": 7}
};
}
Parametri Query
Quando navighi verso una nuova pagina, puoi anche fornire parametri query.
Vediamo come.
// Home page
routeTo(ProfilePage.path, queryParameters: {"user": "7"});
// navigate to profile page
...
// Profile Page
@override
get init => () {
print(widget.queryParameters()); // {"user": 7}
// or
print(queryParameters()); // {"user": 7}
};
Nota: Finche il tuo widget di pagina estende
NyStatefulWidgete la classeNyPage, puoi chiamarewidget.queryParameters()per ottenere tutti i parametri query dal nome della rotta.
// Example page
routeTo(ProfilePage.path, queryParameters: {"hello": "world", "say": "I love code"});
...
// Home page
class MyHomePage extends NyStatefulWidget<HomeController> {
...
}
class _MyHomePageState extends NyPage<MyHomePage> {
@override
get init => () {
widget.queryParameters(); // {"hello": "World", "say": "I love code"}
// or
queryParameters(); // {"hello": "World", "say": "I love code"}
};
Suggerimento: I parametri query devono seguire il protocollo HTTP, Es. /account?userId=1&tab=2
Transizioni di Pagina
Puoi aggiungere transizioni quando navighi da una pagina modificando il tuo file router.dart.
import 'package:page_transition/page_transition.dart';
appRouter() => nyRoutes((router) {
// bottomToTop
router.add(SettingsPage.path,
transitionType: TransitionType.bottomToTop()
);
// fade
router.add(HomePage.path,
transitionType: TransitionType.fade()
);
});
Transizioni di Pagina Disponibili
Transizioni Base
TransitionType.fade()- Dissolve la nuova pagina in entrata mentre dissolve la vecchia pagina in uscitaTransitionType.theme()- Usa il tema delle transizioni di pagina del tema dell'app
Transizioni a Scorrimento Direzionale
TransitionType.rightToLeft()- Scorre dal bordo destro dello schermoTransitionType.leftToRight()- Scorre dal bordo sinistro dello schermoTransitionType.topToBottom()- Scorre dal bordo superiore dello schermoTransitionType.bottomToTop()- Scorre dal bordo inferiore dello schermo
Transizioni Scorrimento con Dissolvenza
TransitionType.rightToLeftWithFade()- Scorre e dissolve dal bordo destroTransitionType.leftToRightWithFade()- Scorre e dissolve dal bordo sinistro
Transizioni di Trasformazione
TransitionType.scale(alignment: ...)- Scala dal punto di allineamento specificatoTransitionType.rotate(alignment: ...)- Ruota attorno al punto di allineamento specificatoTransitionType.size(alignment: ...)- Cresce dal punto di allineamento specificato
Transizioni Congiunte (Richiede il widget corrente)
TransitionType.leftToRightJoined(childCurrent: ...)- La pagina corrente esce a destra mentre la nuova pagina entra da sinistraTransitionType.rightToLeftJoined(childCurrent: ...)- La pagina corrente esce a sinistra mentre la nuova pagina entra da destraTransitionType.topToBottomJoined(childCurrent: ...)- La pagina corrente esce verso il basso mentre la nuova pagina entra dall'altoTransitionType.bottomToTopJoined(childCurrent: ...)- La pagina corrente esce verso l'alto mentre la nuova pagina entra dal basso
Transizioni Pop (Richiede il widget corrente)
TransitionType.leftToRightPop(childCurrent: ...)- La pagina corrente esce a destra, la nuova pagina resta fermaTransitionType.rightToLeftPop(childCurrent: ...)- La pagina corrente esce a sinistra, la nuova pagina resta fermaTransitionType.topToBottomPop(childCurrent: ...)- La pagina corrente esce verso il basso, la nuova pagina resta fermaTransitionType.bottomToTopPop(childCurrent: ...)- La pagina corrente esce verso l'alto, la nuova pagina resta ferma
Transizioni Material Design Shared Axis
TransitionType.sharedAxisHorizontal()- Transizione con scorrimento e dissolvenza orizzontaleTransitionType.sharedAxisVertical()- Transizione con scorrimento e dissolvenza verticaleTransitionType.sharedAxisScale()- Transizione con scala e dissolvenza
Parametri di Personalizzazione
Ogni transizione accetta i seguenti parametri opzionali:
| Parametro | Descrizione | Predefinito |
|---|---|---|
curve |
Curva di animazione | Curve specifiche della piattaforma |
duration |
Durata dell'animazione | Durate specifiche della piattaforma |
reverseDuration |
Durata dell'animazione inversa | Uguale a duration |
fullscreenDialog |
Se la rotta e un dialogo a schermo intero | false |
opaque |
Se la rotta e opaca | false |
// Home page widget
class _HomePageState extends NyPage<HomePage> {
_showProfile() {
routeTo(ProfilePage.path,
transitionType: TransitionType.bottomToTop()
);
}
...
Tipi di Navigazione
Durante la navigazione, puoi specificare uno dei seguenti se stai utilizzando l'helper routeTo.
| Tipo | Descrizione |
|---|---|
NavigationType.push |
Inserisce una nuova pagina nello stack delle rotte della tua app |
NavigationType.pushReplace |
Sostituisce la rotta corrente, eliminando la rotta precedente una volta che la nuova rotta e completata |
NavigationType.popAndPushNamed |
Rimuove la rotta corrente dal navigatore e inserisce una rotta nominata al suo posto |
NavigationType.pushAndRemoveUntil |
Inserisce e rimuove le rotte fino a quando il predicato restituisce true |
NavigationType.pushAndForgetAll |
Naviga verso una nuova pagina e elimina qualsiasi altra pagina nello stack delle rotte |
// Home page widget
class _HomePageState extends NyPage<HomePage> {
_showProfile() {
routeTo(
ProfilePage.path,
navigationType: NavigationType.pushReplace
);
}
...
Navigare indietro
Una volta che sei nella nuova pagina, puoi utilizzare l'helper pop() per tornare alla pagina precedente.
// SettingsPage Widget
class _SettingsPageState extends NyPage<SettingsPage> {
_back() {
pop();
// or
Navigator.pop(context);
}
...
Se vuoi restituire un valore al widget precedente, fornisci un result come nell'esempio seguente.
// SettingsPage Widget
class _SettingsPageState extends NyPage<SettingsPage> {
_back() {
pop(result: {"status": "COMPLETE"});
}
...
// Get the value from the previous widget using the `onPop` parameter
// HomePage Widget
class _HomePageState extends NyPage<HomePage> {
_viewSettings() {
routeTo(SettingsPage.path, onPop: (value) {
print(value); // {"status": "COMPLETE"}
});
}
...
Navigazione Condizionale
Usa routeIf() per navigare solo quando una condizione e soddisfatta:
// Only navigate if the user is logged in
routeIf(isLoggedIn, DashboardPage.path);
// With additional options
routeIf(
hasPermission('view_reports'),
ReportsPage.path,
data: {'filters': defaultFilters},
navigationType: NavigationType.push,
);
Se la condizione e false, non avviene alcuna navigazione.
Cronologia delle Rotte
In Nylo Website, puoi accedere alle informazioni sulla cronologia delle rotte utilizzando gli helper seguenti.
// Get route history
Nylo.getRouteHistory(); // List<dynamic>
// Get the current route
Nylo.getCurrentRoute(); // Route<dynamic>?
// Get the previous route
Nylo.getPreviousRoute(); // Route<dynamic>?
// Get the current route name
Nylo.getCurrentRouteName(); // String?
// Get the previous route name
Nylo.getPreviousRouteName(); // String?
// Get the current route arguments
Nylo.getCurrentRouteArguments(); // dynamic
// Get the previous route arguments
Nylo.getPreviousRouteArguments(); // dynamic
Aggiornare lo Stack delle Rotte
Puoi aggiornare lo stack di navigazione programmaticamente utilizzando NyNavigator.updateStack():
// Update the stack with a list of routes
NyNavigator.updateStack([
HomePage.path,
SettingsPage.path,
ProfilePage.path,
], replace: true);
// Pass data to specific routes
NyNavigator.updateStack([
HomePage.path,
ProfilePage.path,
],
replace: true,
dataForRoute: {
ProfilePage.path: {"userId": 42}
}
);
| Parametro | Tipo | Predefinito | Descrizione |
|---|---|---|---|
routes |
List<String> |
obbligatorio | Lista dei percorsi delle rotte verso cui navigare |
replace |
bool |
true |
Se sostituire lo stack corrente |
dataForRoute |
Map<String, dynamic>? |
null |
Dati da passare a rotte specifiche |
Questo e utile per:
- Scenari di deep linking
- Ripristino dello stato di navigazione
- Costruzione di flussi di navigazione complessi
Deep Linking
Il deep linking consente agli utenti di navigare direttamente a contenuti specifici all'interno della tua app utilizzando URL. Questo e utile per:
- Condividere link diretti a contenuti specifici dell'app
- Campagne di marketing che mirano a funzionalita specifiche nell'app
- Gestione di notifiche che dovrebbero aprire schermate specifiche dell'app
- Transizioni fluide dal web all'app
Configurazione
Prima di implementare il deep linking nella tua app, assicurati che il tuo progetto sia configurato correttamente:
1. Configurazione della Piattaforma
iOS: Configura i link universali nel tuo progetto Xcode
Android: Configura gli app link nel tuo AndroidManifest.xml
2. Definisci le Tue Rotte
Tutte le rotte che dovrebbero essere accessibili tramite deep link devono essere registrate nella configurazione del router:
// File: /lib/routes/router.dart
appRouter() => nyRoutes((router) {
// Basic routes
router.add(HomePage.path).initialRoute();
router.add(ProfilePage.path);
router.add(SettingsPage.path);
// Route with parameters
router.add(HotelBookingPage.path);
});
Utilizzo dei Deep Link
Una volta configurata, la tua app puo gestire URL in arrivo in vari formati:
Deep Link Base
Navigazione semplice verso pagine specifiche:
https://yourdomain.com/profile // Opens the profile page
https://yourdomain.com/settings // Opens the settings page
Per attivare queste navigazioni programmaticamente all'interno della tua app:
routeTo(ProfilePage.path);
routeTo(SettingsPage.path);
Parametri del Percorso
Per rotte che richiedono dati dinamici come parte del percorso:
Definizione della Rotta
class HotelBookingPage extends NyStatefulWidget {
// Define a route with a parameter placeholder {id}
static RouteView path = ("/hotel/{id}/booking", (_) => HotelBookingPage());
HotelBookingPage({super.key}) : super(child: () => _HotelBookingPageState());
}
class _HotelBookingPageState extends NyPage<HotelBookingPage> {
@override
get init => () {
// Access the path parameter
final hotelId = queryParameters()["id"]; // Returns "87" for URL ../hotel/87/booking
print("Loading hotel ID: $hotelId");
// Use the ID to fetch hotel data or perform operations
};
// Rest of your page implementation
}
Formato dell'URL
https://yourdomain.com/hotel/87/booking
Navigazione Programmatica
// Navigate with parameters
routeTo(HotelBookingPage.path.withParams({"id": "87"}), queryParameters: {
"bookings": "active",
});
Parametri Query
Per parametri opzionali o quando sono necessari piu valori dinamici:
Formato dell'URL
https://yourdomain.com/profile?user=20&tab=posts
https://yourdomain.com/hotel/87/booking?checkIn=2025-04-10&nights=3
Accesso ai Parametri Query
class _ProfilePageState extends NyPage<ProfilePage> {
@override
get init => () {
// Get all query parameters
final params = queryParameters();
// Access specific parameters
final userId = params["user"]; // "20"
final activeTab = params["tab"]; // "posts"
// Alternative access method
final params2 = widget.queryParameters();
print(params2); // {"user": "20", "tab": "posts"}
};
}
Navigazione Programmatica con Parametri Query
// Navigate with query parameters
routeTo(ProfilePage.path.withQueryParams({"user": "20", "tab": "posts"}));
// Combine path and query parameters
routeTo(HotelBookingPage.path.withParams({"id": "87"}), queryParameters: {
"checkIn": "2025-04-10",
"nights": "3",
});
Gestione dei Deep Link
Puoi gestire gli eventi di deep link nel tuo RouteProvider:
class RouteProvider implements NyProvider {
@override
setup(Nylo nylo) async {
nylo.addRouter(appRouter());
// Handle deep links
nylo.onDeepLink(_onDeepLink);
return nylo;
}
_onDeepLink(String route, Map<String, String>? data) {
print("Deep link route: $route");
print("Deep link data: $data");
// Update the route stack for deep links
if (route == ProfilePage.path) {
NyNavigator.updateStack([
HomePage.path,
ProfilePage.path,
], replace: true, dataForRoute: {
ProfilePage.path: data,
});
}
}
@override
boot(Nylo nylo) async {
nylo.initRoutes();
}
}
Test dei Deep Link
Per lo sviluppo e il test, puoi simulare l'attivazione dei deep link utilizzando ADB (Android) o xcrun (iOS):
# Android
adb shell am start -a android.intent.action.VIEW -d "https://yourdomain.com/profile?user=20" com.yourcompany.yourapp
# iOS (Simulator)
xcrun simctl openurl booted "https://yourdomain.com/profile?user=20"
Suggerimenti per il Debug
- Stampa tutti i parametri nel tuo metodo init per verificare il parsing corretto
- Testa diversi formati di URL per assicurarti che la tua app li gestisca correttamente
- Ricorda che i parametri query vengono sempre ricevuti come stringhe, convertili nel tipo appropriato secondo necessita
Pattern Comuni
Conversione del Tipo dei Parametri
Poiche tutti i parametri URL vengono passati come stringhe, spesso avrai bisogno di convertirli:
// Converting string parameters to appropriate types
final hotelId = int.parse(queryParameters()["id"] ?? "0");
final isAvailable = (queryParameters()["available"] ?? "false") == "true";
final checkInDate = DateTime.parse(queryParameters()["checkIn"] ?? "");
Parametri Opzionali
Gestisci i casi in cui i parametri potrebbero mancare:
final userId = queryParameters()["user"];
if (userId != null) {
// Load specific user profile
} else {
// Load current user profile
}
// Or check hasQueryParameter
if (hasQueryParameter('status')) {
// Do something with the status parameter
} else {
// Handle absence of the parameter
}
Avanzato
Verificare se una Rotta Esiste
Puoi verificare se una rotta e registrata nel tuo router:
if (Nylo.containsRoute("/profile")) {
routeTo("/profile");
}
Metodi NyRouter
La classe NyRouter fornisce diversi metodi utili:
| Metodo | Descrizione |
|---|---|
getRegisteredRouteNames() |
Ottieni tutti i nomi delle rotte registrate come lista |
getRegisteredRoutes() |
Ottieni tutte le rotte registrate come mappa |
containsRoutes(routes) |
Verifica se il router contiene tutte le rotte specificate |
getInitialRouteName() |
Ottieni il nome della rotta iniziale |
getAuthRouteName() |
Ottieni il nome della rotta autenticata |
getUnknownRouteName() |
Ottieni il nome della rotta sconosciuta/404 |
Ottenere gli Argomenti della Rotta
Puoi ottenere gli argomenti della rotta utilizzando NyRouter.args<T>():
class _ProfilePageState extends NyPage<ProfilePage> {
@override
Widget build(BuildContext context) {
// Get typed arguments
final args = NyRouter.args<NyArgument>(context);
final userData = args?.data;
return Scaffold(...);
}
}
NyArgument e NyQueryParameters
I dati passati tra le rotte sono incapsulati in queste classi:
// NyArgument contains route data
NyArgument argument = NyArgument({'userId': 42});
print(argument.data); // {'userId': 42}
// NyQueryParameters contains URL query parameters
NyQueryParameters params = NyQueryParameters({'tab': 'posts'});
print(params.data); // {'tab': 'posts'}