Home > Blockchain >  Observing LiveData in JetPack Composable
Observing LiveData in JetPack Composable

Time:12-06

I am practicing JetPack Compose with a pet app and I'm trying to observe a loading state in a Splash screen via LiveData. But, inside my composable I am asked to provide viewLifecycleOwner which seems impossible inside a composable. Or do I need to pass it down from the MainActivity? Seems clunky, is there another, more Jetpacky way?

@Composable
fun SplashScreen(navController: NavHostController, isLoadingInit: LiveData<Boolean>) {
    val scale = remember {
        Animatable(0f)
    }
    
    LaunchedEffect(key1 = true) {
        scale.animateTo(
            targetValue = 0.5f,
            animationSpec = tween(
                durationMillis = 500,
                easing = {
                    OvershootInterpolator(2f).getInterpolation(it)
                }
            )
        )
    }

    Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
        Image(
            painter = painterResource(id = R.drawable.pokeball),
            contentDescription = "Pokemon Splashscreen",
            modifier = Modifier.scale(scale.value)
        )
    }

    isLoadingInit.observe(**viewLifecycleOwner**) {
        navController.navigate("main-screen")
    }
}

CodePudding user response:

You can convert your LiveData to State using LiveData.observeAsState() extension function. Also instead of passing a LiveData as a parameter to compose, prefer converting it to a State first and then pass that as a parameter.

// This is probably what you are doing right now (inside a NavGraph)
val isLoadingInit = viewModel.isLoadingInit
SplashScreen(navController, isLoadingInit)

Change it to:

val isLoadingInit by viewModel.isLoadingInit.observeAsState()
SplashScreen(navController, isLoadingInit)

And then,

@Composable
fun SplashScreen(navController: NavHostController, isLoadingInit: Boolean) {
    LaunchedEffect(isLoadingInit) {
        if(!isLoadingInit) // Or maybe its negation
            navController.navigate("main-screen")
    }
    ...
}
  • Related