Tung
Tung

Reputation: 25

LaunchedEffect vs rememberCoroutineScope. This explanation makes me confused. Please make it clear to me

I am following the codelab Advanced State and Side Effects in Jetpack Compose. It says that if we use rememberCoroutineScope instead of LaunchEffect in this case, it seems to work, but it is not correct. "As explained in the Thinking in Compose documentation, composables can be called by Compose at any moment. LaunchedEffect guarantees that the side-effect will be executed when the call to that composable makes it into the Composition. If you use rememberCoroutineScope and scope.launch in the body of the LandingScreen, the coroutine will be executed every time LandingScreen is called by Compose regardless of whether that call makes it into the Composition or not. Therefore, you'll waste resources and you won't be executing this side-effect in a controlled environment."

@Composable
private fun MainScreen(onExploreItemClicked: OnExploreItemClicked) {
    Surface(color = MaterialTheme.colors.primary) {
        var showLandingScreen by remember { mutableStateOf(true) }

        if (showLandingScreen) {
            LandingScreen(onTimeout = { showLandingScreen = false })
        } else {
            CraneHome(onExploreItemClicked = onExploreItemClicked)
        }
    }
}

@Composable
fun LandingScreen(modifier: Modifier = Modifier, onTimeout: () -> Unit) {
    Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        // TODO Codelab: LaunchedEffect and rememberUpdatedState step
        // TODO: Make LandingScreen disappear after loading data
        val onCurrentTimeout by rememberUpdatedState(newValue = onTimeout)
        LaunchedEffect(Unit) {
            delay(SplashWaitTime)
            onCurrentTimeout()
        }
        Image(painterResource(id = R.drawable.ic_crane_drawer), contentDescription = null)
    }
}

I do not understand the explanation. The phrases "when the call to that composable makes it into the Composition" and "regardless of whether that call makes it into the Composition or not" make me confused. I think when a composable is called by Compose, it will be in the Composition. How can it be not in the Composition after being called? Please show me what I miss here.

Upvotes: 1

Views: 2005

Answers (1)

Thracian
Thracian

Reputation: 67423

When a Composable enters composition LaunchedEffect() gets triggered. If LaunchedEffect has key or keys it can be triggered on recompositions when key values change.

@Composable
private fun MyTestComposable() {
    var counter by remember { mutableStateOf(0) }
    Column(modifier = Modifier.fillMaxSize()) {

        LaunchedEffect(key1 = counter>4) {
            println("counter: $counter")
        }
        Button(onClick = { counter++ }) {
            Text("counter: $counter")
        }
    }
}

For instance, LaunchedEffect block gets triggered when key change. First when MyTestComposable enters composition with false flag and when counter is 5 with true flag.

rememberCoroutineScope on the other hand launches every time your function is run. It's very very likely to enter composition but there might be times state that triggers composition change fast so current composition gets canceled and new one is scheduled

Recomposition starts whenever Compose thinks that the parameters of a composable might have changed. Recomposition is optimistic, which means Compose expects to finish recomposition before the parameters change again. If a parameter does change before recomposition finishes, Compose might cancel the recomposition and restart it with the new parameter.

When recomposition is canceled, Compose discards the UI tree from the recomposition. If you have any side-effects that depend on the UI being displayed, the side-effect will be applied even if composition is canceled. This can lead to inconsistent app state.

Ensure that all composable functions and lambdas are idempotent and side-effect free to handle optimistic recomposition.

https://developer.android.com/jetpack/compose/mental-model#optimistic

Upvotes: 1

Related Questions