Home > database >  How to trigger navigation after viewmodel is loaded with Jetpack Compose Navigation
How to trigger navigation after viewmodel is loaded with Jetpack Compose Navigation

Time:11-11

I am creating a simple application using compose, which shows a loading screen while API data is being loaded. The screen shows a progress bar while it loads, then upon loading the data into the view model, it is supposed to navigate forward to the main screen, which will use the data. I am creating a loading screen for my application, and I got stuck with trying to make the application navigate to the home screen of my application, after the viewModel of the loading screen is loaded. Since it is at an early stage, the data loading in the viewmodel is not yet implemented, I would like to make placeholder code with a small delay, before that is done.

My main activity contains the navhost:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyTheme() {
                MyNavHost()
            }
        }
    }
}

@Composable
fun MyNavHost(
    navController: NavHostController = rememberNavController(),
) {
    NavHost(navController = navController, startDestination = "loadingScreen") {
        composable("loadingScreen") {
            LoadingScreen(
                onNavigateToMainScreen = { navController.navigate("mainScreen") }
            )
        }
        composable("mainScreen") { MainScreen() }
    }
}

And my Loading screen:

@Composable
fun LoadingScreen(onNavigateToMainScreen: () -> Unit) {
    val viewModel by remember {
        mutableStateOf(LoadingScreenViewModel())
    }
    MyTheme {
        Box(
            modifier = Modifier.fillMaxSize(),
            contentAlignment = Alignment.Center) {
            CircularProgressIndicator()
        }
    }
    onNavigateToMainScreen()
}

And my view model:

class LoadingScreenViewModel: ViewModel() {
    init {
        viewModelScope.launch {
            delay(500)
        }
    }
}

This results in the app crashing, and I do not really have any logic in place to check the loaded state of the view model, how to do that is also part of my question. I am new to compose and navigation, so any direction you can point me to is much appreciated.

CodePudding user response:

Do it directly in the LoadingScreen composable for now:

@Composable
fun LoadingScreen(onNavigateToMainScreen: () -> Unit) {
   
    LaunchedEffect(Unit){
        delay(500)
        onNavigateToMainScreen()
    }

    MyTheme {
        Box(
            modifier = Modifier.fillMaxSize(),
            contentAlignment = Alignment.Center) {
            CircularProgressIndicator()
        }
    }
}

probably having a whole screen only for the loading indicator is a bit overkill. If you have data from the viewmodel, just use the state of the data to trigger a visibility animation, something like:

@Composable
fun MainScreen(){
    val viewModel : MyViewModel by viewModel()
    val list : MutableState<List<Any>> = viewModel.items
     
     Box{
           AnimatedVisibility(visible = list.isEmpty()){
              CircularProgressIndicator()
           }
           LazyColumn{ items(list)
        }
    }
}
  • Related