Todo sobre navegar por la base de código de producción basada en Jetpack Compose | de Kaaveh Mohamedi | enero 2023

Es común en la mayoría de las aplicaciones de Android tener múltiples pantallas con navegación inferior. En este artículo, explicaré cómo administrar el material de navegación en una aplicación Jetpack Compose, mencionaré algunos problemas comunes que pueden surgir y la solución que puede ser necesaria.La foto de Mahdiar Mahmoodi en UnsplashLet asume que estamos trabajando en un rico código base de producción multimodular y comenzando a migrarlo a Jetpack Compose. ¿Cómo lidiamos con las cosas de navegación? Aquí tenemos dos campos; la navegación inferior y la navegación entre pantallas.

Conceptos básicos de la navegación de configuración

Primero configure un NavHost en MainActivity usando Scaffold y este será el gráfico de navegación principal: @Composablefun MyAppNavHost(navController: NavHostController,modifier: Modifier,) { NavHost(navController = navController,startDestination = Destinations.NewsListScreen.route,modifier = modifier , ) { // pantallas de navegación inferiores y gráficos anidadosnewsListGraph(navController)favoriteNewsGraph(navController)profileGraph(navController)// pantallas comunes en la aplicaciónnewsDetailGraph()…}} Para evitar crear un gran gráfico de navegación principal, lo dividimos para separarlo pantallas y gráficos anidados. De hecho, cada pantalla tiene su propio componible envuelto por una función de extensión NavGraphBuilder. Para una pantalla común sería la siguiente: fun NavGraphBuilder.VerifyCodeGraph() {composable(route = Destinations.VerifyCodeScreen().route,) {VerifyCodeScreen()}}Para administrar la ruta de cada pantalla podemos usar una clase sellada como esta: Destinos de clase sellada (ruta val: String) {objeto NewsListScreen: Destinos («news_list_screen») clase de datos NewsDetailScreen (val news: String = «news»): Destinos («news_detail_screen») : Destinations («news_detail_screen») object FavoriteNewsScreen : Destinations («favorite_news_screen») object ProfileScreen : Destination(«profile_screen»)object SettingScreen : Destination(«setting_screen»)object ThemeScreen : Destination(«theme_screen»)object LoginScreen : Destination(«login_screen»)object VerifyCodeScreen : Destination(«verify_code_screen»)…} Entonces, si cada pantalla necesita algunos parámetros, se podría incrustar una clase de datos en la pantalla, como la clase de datos NewsDetailScreen(val news: String=»news»). Si una pantalla necesita navegar a otra pantalla, simplemente pase una función para manejar eso: Fun NavGraphBui lder.settingListGraph(navController: NavController,) {composable(Destinations.SettingScreen.route) {NewsListRoute(onNavigateToThemeScreen = {navController.navigate (route = Destinations.ThemeScreen().route,)})}} De esta manera, no hay necesidad de hacer que su módulo de funciones dependa de la biblioteca de navegación. Es responsabilidad del módulo de la aplicación manejar los asuntos de navegación. Si algunas pantallas se pueden agrupar en un gráfico anidado, haga lo siguiente: fun NavGraphBuilder.profileGraph(navController: NavHostController) { navigation(startDestination = Destination.ProfileScreen.route,route = Destination .ProfileScreen.route.addGraphPostfix(),) {componible (Destination.ProfileScreen.route) {ProfileScreen(onNavigationToLoginScreen = {navController.navigate(route = Destination.LoginScreen.route.addGraphPostfix(),)})}loginGraph()}} Para gráficos anidados, considere estos consejos:

  1. Cada gráfico de navegación anidado debe tener un destino de inicio
  2. Cada navGraph anidado, como otros componibles, debe tener una ruta única. Una solución simple es usar la ruta startDestination + «_graph»
  3. Puede agregar fácilmente otros gráficos componibles y anidados a este gráfico

Para configurar la barra de navegación inferior, simplemente siga el medico. Si quieres deeplink sigue este departamento.

pasar argumentos

Otra necesidad en la navegación es pasar algunos argumentos. Para pasar datos primitivos puedes seguir el medico. Pero en algunos escenarios necesita pasar un objeto. Actualmente (principios de 2023) no existe una solución para usar la navegación () con una ruta, pero hay una sobrecarga que acepta un paquete: navegación pública abierta y divertida (@IdRes resId: Int,args: Bundle?,navOptions: NavOptions?,navigatorExtras : Navigator.Extras?)‌Como puede ver, obtiene una identificación para el objetivo. Escribamos una función de extensión para poder usarla: fun NavController.navigate(ruta: String,args: Bundle,navOptions: NavOptions? = null,navigatorExtras: Navigator.Extras? = null) { val routeLink = NavDeepLinkRequest.Builder. fromUri( NavDestination.createRoute(ruta).toUri()).build()val deepLinkMatch = graph.matchDeepLink(routeLink)if (deepLinkMatch != null) {val destino = deepLinkMatch.destinationval id = destino.idnavigate(id, args, navOptions, navigatorExtras)} else {navigate(route, navOptions, navigatorExtras)}} Y para usar esta función en la pantalla de origen: fun NavGraphBuilder.newsListGraph(navController: NavController,) {composable(Destinations.NewsListScreen.route) {NewsListScreen(onNavigateToDetailScreen = { noticias ->navController.navigate(ruta = Destinations.NewsDetailScreen().route,args = bundleOf(Destinations.NewsDetailScreen().news to news))})}}En la pantalla de destino: fun NavGraphBuilder.newsDetailScreen() {componible( ruta = metas .NewsDetailScreen().route,) { entrada ->val noticias = entrada.parcelableData(Destinos.NewsDetailScreen().news)NewsDetailScreen(noticias = noticias,)}} diversión en línea NavBackStackEntry.parcelableData(clave: Cadena): T? {argumentos de retorno? .parcelable (clave) como? T}

Deja una respuesta

Tu dirección de correo electrónico no será publicada.