es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

java.lang.IllegalStateException: No se puede acceder a los ViewModels de NavBackStackEntry hasta que se agregue a la pila de retroceso del NavController.

He creado un compuesto llamado ResolveAuth. ResolveAuth es la primera pantalla que se muestra cuando el usuario abre la aplicación después de Splash. Todo lo que hace es verificar si hay un correo electrónico presente en Datastore o no. Si es así, redirige a la pantalla principal y si no, redirige a la pantalla de tutorial.

Aquí está mi código compuesto y de viewmodel:

@Composable
fun ResolveAuth(resolveAuthViewModel: ResolveAuthViewModel, navController: NavController) {

Scaffold(content = {
ProgressBar()

   when {
       resolveAuthViewModel.userEmail.value != "" -> {
           navController.navigate(Screen.Main.route) {
               popUpTo(0)
           }
           resolveAuthViewModel.userEmail.value = null
       }
       resolveAuthViewModel.userEmail.value == "" -> {
           navController.navigate(Screen.Tutorial.route) {
               popUpTo(0)
           }
           resolveAuthViewModel.userEmail.value = null
       }
   }

})
}

@HiltViewModel
class ResolveAuthViewModel @Inject constructor(
private val dataStoreManager: DataStoreManager): ViewModel(){

val userEmail = MutableLiveData()

init {
viewModelScope.launch{
val job = async {dataStoreManager.email.first()}
val email = job.await()
if(email != “”){
userEmail.value = email
}
}
}

}

Pero sigo obteniendo una excepción que dice:

java.lang.IllegalStateException: No se puede acceder a los ViewModels de NavBackStackEntry hasta que se agregue a la pila de retroceso de NavController (es decir, hasta que el ciclo de vida de NavBackStackEntry alcance el estado CREADO).

Estoy utilizando la siguiente biblioteca de jetpack para la navegación:

implementation(“androidx.navigation:navigation-compose:2.4.0-rc01”)

No hay problema en mi pantalla principal y de tutorial, ya que intenté ejecutarlas por separado y funcionan bien.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    La excepción que estás obteniendo indica que estás intentando acceder a los ViewModels de NavBackStackEntry antes de que se agregue a la pila de navegación de NavController. En otras palabras, el ciclo de vida de NavBackStackEntry aún no ha alcanzado el estado CREATED.

    Para resolver este problema, puedes envolver tu composición dentro del componible NavHost del componente de navegación, que maneja automáticamente la creación y el ciclo de vida de NavBackStackEntry.

    Aquí tienes un ejemplo de cómo hacerlo:

    1. Dentro de la función o componible setContent de tu aplicación, envuelve tu NavHost con tu componible de nivel superior, en este caso, ResolveAuth:
      setContent {
         MyTheme{
             NavHost(
                 navController = navController,
                 startDestination = Screen.ResolveAuth.route
             ){
                   composable(Screen.ResolveAuth.route){
                        ResolveAuth(
                            resolveAuthViewModel = hiltViewModel(),
                            navController = navController
                        )
                   }
                   composable(Screen.Main.route){
                        MainScreen(mainViewModel = hiltViewModel(), navController = navController)
                   }
                   composable(Screen.Tutorial.route){
                        TutorialScreen(tutorialViewModel = hiltViewModel(), navController = navController)
                   }
             }
         }
      }
      
    2. Modifica tu componible ResolveAuth para eliminar el Scaffold y agregar un Column en su lugar. Dentro del componible Column, añade el ProgressBar y la lógica de navegación.
      @Composable
      fun ResolveAuth(resolveAuthViewModel: ResolveAuthViewModel, navController: NavController) {
         Column(
             modifier = Modifier.fillMaxSize(),
             verticalArrangement = Arrangement.Center,
             horizontalAlignment = Alignment.CenterHorizontally
         ) {
             ProgressBar()
      
             LaunchedEffect(Unit) {
                 val email = resolveAuthViewModel.getUserEmail()
                 if (email != "") {
                     navController.navigate(Screen.Main.route) {
                         popUpTo(0)
                     }
                 } else {
                     navController.navigate(Screen.Tutorial.route) {
                         popUpTo(0)
                     }
                 }
             }
         }
      }
      
    3. Modifica tu ResolveAuthViewModel para que devuelva el valor del correo electrónico en lugar de actualizar el live data userEmail.
      @HiltViewModel
      class ResolveAuthViewModel @Inject constructor(
         private val dataStoreManager: DataStoreManager
      ) : ViewModel() {
         suspend fun getUserEmail(): String = dataStoreManager.email.first()
      }
      

    Con estos cambios, tu componible ResolveAuth está ahora correctamente envuelto dentro del NavHost del componente de navegación. Debería solucionar la excepción que estabas obteniendo y manejar la navegación basada en el valor del correo electrónico en Datastore.

Comments are closed.