Sicurezza dei tipi in Kotlin DSL e Navigation Compose

Puoi utilizzare le API integrate con controllo del tipo per fornire la sicurezza del tipo in fase di compilazione per il tuo grafico di navigazione. Queste API sono disponibili quando la tua app utilizza Navigation Compose o Navigation Kotlin DSL. Sono disponibili a partire dal giorno Navigation 2.8.0.

Queste API sono equivalenti a quelle fornite da Safe Args ai grafici di navigazione creati utilizzando XML.

Definisci le route

Per utilizzare route type-safe in Compose, devi prima definire classi o oggetti serializzabili che rappresentino le tue route.

Per definire oggetti serializzabili, utilizza l'annotazione @Serializable fornita dal plug-in Kotlin Serialization. Questo plug-in può essere aggiunto al tuo progetto aggiungendo queste dipendenze.

Utilizza le seguenti regole per decidere quale tipo utilizzare per il tuo percorso:

  • Object: utilizza un oggetto per le route senza argomenti.
  • Classe: utilizza una classe o una classe di dati per le route con argomenti.
  • KClass<T>: utilizza questo valore se non devi passare argomenti, ad esempio una classe senza parametri o una classe in cui tutti i parametri hanno valori predefiniti
    1. Ad esempio: Profile::class

In tutti i casi, l'oggetto o la classe devono essere serializzabili.

Ad esempio:

// Define a home route that doesn't take any arguments
@Serializable
object Home

// Define a profile route that takes an ID
@Serializable
data class Profile(val id: String)

Creare il grafico

A questo punto devi definire il grafico di navigazione. Utilizza la funzione composable() per definire i composable come destinazioni nel grafico di navigazione.

NavHost(navController, startDestination = Home) {
     composable<Home> {
         HomeScreen(onNavigateToProfile = { id ->
             navController.navigate(Profile(id))
         })
     }
     composable<Profile> { backStackEntry ->
         val profile: Profile = backStackEntry.toRoute()
         ProfileScreen(profile.id)
     }
}

In questo esempio, osserva quanto segue:

  • composable() accetta un parametro di tipo. ovvero composable<Profile>.
  • Definire il tipo di destinazione è un approccio più solido rispetto al passaggio di una route stringa come in composable("profile").
  • La classe di route definisce il tipo di ogni argomento di navigazione, come in val id: String, quindi non è necessario NavArgument.
  • Per la route del profilo, il metodo di estensione toRoute() ricrea l'oggetto Profile da NavBackStackEntry e dai relativi argomenti.

Per ulteriori informazioni su come progettare il grafico in generale, consulta la pagina Progettare il grafico di navigazione.

Accedere agli argomenti in un ViewModel

Per accedere agli argomenti da una route type-safe in un ViewModel, puoi recuperare la route da SavedStateHandle chiamando SavedStateHandle.toRoute<T>(), dove T è la classe della route:

class ProfileViewModel(
    savedStateHandle: SavedStateHandle
) : ViewModel() {
    private val profile = savedStateHandle.toRoute<Profile>()
    private val userInfo: Flow<UserInfo> = userInfoRepository.getUserInfo(profile.id)
}

Infine, puoi passare all'elemento composable utilizzando la funzione navigate() passando l'istanza della route:

navController.navigate(Profile(id = 123))

In questo modo, l'utente viene indirizzato alla destinazione composable<Profile> nel grafico di navigazione. Qualsiasi argomento di navigazione, ad esempio id, può essere ottenuto ricostruendo Profile utilizzando NavBackStackEntry.toRoute e leggendone le proprietà.

Risorse aggiuntive