La API de Navigation Compose te permite navegar entre elementos componibles en una app de Compose y, al mismo tiempo, aprovechar el componente, la infraestructura y las funciones de Jetpack Navigation.
En esta página, se describe cómo migrar de una navegación de Jetpack basada en Fragment a Navigation Compose, como parte de la migración más grande de la IU basada en View a Jetpack Compose.
Requisitos previos para la migración
Puedes migrar a Navigation Compose una vez que puedas reemplazar todos tus fragmentos por elementos componibles de pantalla correspondientes. Los elementos componibles de la pantalla pueden contener una combinación de contenido de Compose y View, pero todos los destinos de navegación deben ser componibles para habilitar la migración de Navigation Compose. Hasta entonces, debes seguir usando el componente Navigation basado en fragmentos en tu código base de interoperabilidad de View y Compose. Consulta la documentación sobre la interoperabilidad de la navegación para obtener más información.
No es un requisito previo usar Navigation Compose en una app solo de Compose. Puedes seguir usando el componente de Navigation basado en fragmentos, siempre y cuando conserves los fragmentos para alojar tu contenido componible.
Pasos de la migración
Ya sea que sigas nuestra estrategia de migración recomendada o adoptes otro enfoque, llegarás a un punto en el que todos los destinos de navegación sean elementos componibles de pantalla, y los fragmentos actúen solo como contenedores componibles. En esta etapa, puedes migrar a Navigation Compose.
Si tu app ya sigue un patrón de diseño de UDF y nuestra guía de arquitectura, la migración a Jetpack Compose y Navigation Compose no debería requerir refactorizaciones importantes de otras capas de tu app, aparte de la capa de IU.
Para migrar a Navigation Compose, sigue estos pasos:
- Agrega la dependencia Navigation Compose a tu app.
Crea un elemento
App-level
componible y agrégalo a tuActivity
como punto de entrada de Compose, reemplazando la configuración del diseño de View:class SampleActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // setContentView<ActivitySampleBinding>(this, R.layout.activity_sample) setContent { SampleApp(/* ... */) } } }
Crea tipos para cada destino de navegación. Usa un
data object
para los destinos que no requieren datos ydata class
oclass
para los destinos que sí los requieren.@Serializable data object First @Serializable data class Second(val id: String) @Serializable data object Third
Configura el
NavController
en un lugar donde todos los elementos componibles que necesiten hacer referencia a él tengan acceso (por lo general, dentro de tu elemento componibleApp
). Este enfoque sigue los principios de la elevación de estado y te permite usarNavController
como la fuente de confianza para navegar entre pantallas componibles y mantener la pila de actividades:@Composable fun SampleApp() { val navController = rememberNavController() // ... }
Crea el
NavHost
de tu app dentro del elementoApp
componible y pasa elnavController
:@Composable fun SampleApp() { val navController = rememberNavController() SampleNavHost(navController = navController) } @Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = First) { // ... } }
Agrega los destinos
composable
para compilar tu gráfico de navegación. Si cada pantalla se migró previamente a Compose, este paso solo consiste en extraer los elementos componibles de estas pantallas de tus fragmentos a los destinos decomposable
:class FirstFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { return ComposeView(requireContext()).apply { setContent { // FirstScreen(...) EXTRACT FROM HERE } } } } @Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = First) { composable<First> { FirstScreen(/* ... */) // EXTRACT TO HERE } composable<Second> { SecondScreen(/* ... */) } // ... } }
Si seguiste la guía para arquitecturar tu IU de Compose, específicamente cómo se deben pasar los
ViewModel
s y los eventos de navegación a los elementos componibles, el siguiente paso es cambiar la forma en que proporcionas elViewModel
a cada elemento componible de la pantalla. A menudo, puedes usar la inyección de Hilt y su punto de integración con Compose y Navigation a través dehiltViewModel
:@Composable fun FirstScreen( // viewModel: FirstViewModel = viewModel(), viewModel: FirstViewModel = hiltViewModel(), onButtonClick: () -> Unit = {}, ) { // ... }
Reemplaza todas las llamadas de navegación
findNavController()
por lasnavController
y pasa estas como eventos de navegación a cada pantalla componible, en lugar de pasar elnavController
completo. Este enfoque sigue las prácticas recomendadas para exponer eventos de funciones de componibilidad a quienes las llaman y mantiene elnavController
como la única fuente de confianza.Para pasar datos a un destino, crea una instancia de la clase de ruta definida para ese destino. Luego, se puede obtener directamente desde la entrada de la pila de actividades en el destino o desde un
ViewModel
conSavedStateHandle.toRoute()
.@Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = First) { composable<First> { FirstScreen( onButtonClick = { // findNavController().navigate(firstScreenToSecondScreenAction) navController.navigate(Second(id = "ABC")) } ) } composable<Second> { backStackEntry -> val secondRoute = backStackEntry.toRoute<Second>() SecondScreen( id = secondRoute.id, onIconClick = { // findNavController().navigate(secondScreenToThirdScreenAction) navController.navigate(Third) } ) } // ... } }
Quita todos los Fragments, los diseños XML pertinentes, la navegación innecesaria y otros recursos, así como las dependencias obsoletas de Fragment y Jetpack Navigation.
Puedes encontrar los mismos pasos con más detalles relacionados con Navigation Compose en la documentación de configuración.
Casos de uso comunes
Independientemente del componente de Navigation que utilices, se aplican los mismos principios de navegación.
Estos son algunos casos de uso comunes cuando se realiza la migración:
- Cómo navegar a un elemento componible
- Cómo navegar con argumentos
- Vínculos directos
- Navegación anidada
- Integración con la barra de navegación inferior
- Integración con un componente de navegación personalizado
Para obtener información más detallada sobre estos casos de uso, consulta Navegación con Compose.
Cómo recuperar datos complejos durante la navegación
Te recomendamos que no pases objetos de datos complejos cuando navegues. En su lugar, pasa la información mínima necesaria, como un identificador único o alguna otra forma de ID, como argumentos, cuando se realizan acciones de navegación. Debes almacenar los objetos complejos como datos en una sola fuente de información, como la capa de datos. Para obtener más información, consulta Cómo recuperar datos complejos durante la navegación.
Si tus fragmentos pasan objetos complejos como argumentos, considera refactorizar tu código primero, de manera que permita almacenar y recuperar estos objetos de la capa de datos. Consulta el repositorio de Now in Android para ver ejemplos.
Limitaciones
En esta sección, se describen las limitaciones actuales de Navigation Compose.
Migración incremental a Navigation Compose
Actualmente, no puedes usar Navigation Compose y, al mismo tiempo, usar fragmentos como destinos en tu código. Para comenzar a usar Navigation Compose, todos tus destinos deben ser elementos componibles. Puedes hacer un seguimiento de esta solicitud de función en la herramienta de seguimiento de errores.
Animaciones de transición
A partir de Navigation 2.7.0-alpha01, la compatibilidad para establecer transiciones personalizadas, que antes se realizaba desde AnimatedNavHost
, ahora se admite directamente en NavHost
. Lee las notas de la versión para obtener más información.
Más información
Para obtener más información sobre la migración a Navigation Compose, consulta los siguientes recursos:
- Codelab de Navigation Compose: Aprende los conceptos básicos de Navigation Compose con un codelab práctico.
- Repositorio de Now in Android: Una app para Android totalmente funcional compilada por completo con Kotlin y Jetpack Compose, que sigue las prácticas recomendadas de diseño y desarrollo de Android, y que incluye Navigation Compose.
- Migración de Sunflower a Jetpack Compose: Una entrada de blog que documenta el proceso de migración de la app de ejemplo de Sunflower de Views a Compose, que también incluye la migración a Navigation Compose.
- Jetnews para todas las pantallas: Una entrada de blog que documenta la refactorización y la migración de la muestra de Jetnews para admitir todas las pantallas con Jetpack Compose y Navigation Compose.
Recomendaciones para ti
- Nota: El texto del vínculo se muestra cuando JavaScript está desactivado
- Cómo navegar con Compose
- Compose y otras bibliotecas
- Otras consideraciones