Search code examples
androidkotlinandroid-jetpack-compose

How LaunchedEffect works


I don't really understand how LauchedEffect works, can you explain to me?

Here is the context, I make a account.get() call to find out if a user session exist or not in my app, depending on the case I return userExist = true or = false

But in all cases it returns me a return = true to know that I must launch my LaunchedEffect at that moment, here is my code

SplashUiState:

data class SplashUiState(
  val result: Boolean = false,
  val userExist: Boolean = false,
  val error: List<Pair<String, String>> = emptyList()
)

SplashViewModel:

private val _state = MutableStateFlow(SplashUiState())
val state = _state.asStateFlow()

...

init {
  delay(2000)
  checkSessionExist()
}

...

private suspend fun checkSessionExist() {
    when(val account = repository.getAccount()) {
        is ResponseResult.Error -> {
            Log.d("SplashViewModel", "${account.code}" + " ${account.message}")
            _state.update { it.copy(result = true, userExist = false,
                userError = listOf(
                    "code" to "${account.code}",
                    "message" to "${account.message}"
                )
            ) }
        }

        is ResponseResult.Success -> {
            Log.d("SplashViewModel", "${account.data}")
            _state.update { it.copy(result = true, userExist = true) }
        }
    }
}

SplashScreen:

val state by viewModel.state.collectAsState()

LaunchedEffect(key1 = state.result) {
  if (state.userExist) {
    Log.d("LaunchedEffect", "user exist")
    navController.navigate(AppRoutes.OVIDE_SCREEN) {
      popUpTo(AppRoutes.SPLASH_SCREEN) {
        inclusive = true
      }
    }
  } else {
    Log.d("LaunchedEffect", "user not exist")
    navController.navigate(AppRoutes.WELCOME_SCREEN) {
      popUpTo(AppRoutes.SPLASH_SCREEN) {
        inclusive = true
      }
    }
  }
}

My code seems good to me, well structured but when the user exists userExist = true it launches my code in the else and not in my if

How is this done?


Solution

  • The code line

    LaunchedEffect(key1 = state.result) {}
    

    means that the code within the LaunchedEffect will be executed

    • one time initially
    • and then whenever the value of state.result changes.

    It does not mean that the LaunchedEffect will only be executed once the state.result value is true. So your app will immediately go to the WELCOME_SCREEN before it even finished checking whether the session exists.

    Please try to change your code like this:

    LaunchedEffect(key1 = state.result) {
        if (state.result) {
            if (state.userExist) {
                Log.d("LaunchedEffect", "user exist")
                navController.navigate(AppRoutes.OVIDE_SCREEN) {
                    popUpTo(AppRoutes.SPLASH_SCREEN) { inclusive = true }
                }
            } else {
                Log.d("LaunchedEffect", "user not exist")
                navController.navigate(AppRoutes.WELCOME_SCREEN) {
                    popUpTo(AppRoutes.SPLASH_SCREEN) { inclusive = true }
                }
            }
        }
    }
    

    This will make the navigation happen once loading is finished.