Reputation: 1326
Read this LaunchedEffect take a variable number of keys as a parameter that are used to restart the effect whenever one of those keys changes.
from here.
I am trying it out by changing the key and check if the LaunchEffect would be relaunched.
Here is my code:
private const val SplashWaitTime: Long = 2000
@Composable
fun LandingScreen(modifier: Modifier = Modifier, onTimeout: () -> Unit) {
Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
val currentOnTimeout by rememberUpdatedState(onTimeout)
var key = 1
LaunchedEffect(key) {
Log.w("xx", "Launched effect is running key = $key")
delay(SplashWaitTime)
key = 2
currentOnTimeout()
}
key = 3
Image(painterResource(id = R.drawable.ic_crane_drawer), contentDescription = null)
}
}
With code above, running the app, and I can see there is only one log print in the Logcat.
Which is:
2022-05-08 18:42:35.951 20101-20101/androidx.compose.samples.crane W/xx: Launched effect is running key = 3
So questions are:
Update:
My Android Studio:
Android Studio Chipmunk | 2021.2.1 Beta 4
Build #AI-212.5712.43.2112.8233820, built on March 1, 2022
Runtime version: 11.0.12+0-b1504.28-7817840 x86_64
My compose version is 1.1.1
Update 2: I accept the answer from @MARSK. Just want to put more info at here for other buddy's information.
I was following the codepath this this codelab. So the code above was a part of it, the key point here I think is:
remember { mutableStateOf(1) }
Why I wasn't able to figuring out how it works, and I got only 1 log print? That was because of the onTimeout callback, from parent level of LandingScreen composable, the function will remove this(LandingScreen) composable completely from the tree, thus it won't have any chance to be re-composed.
Upvotes: 3
Views: 3208
Reputation: 6817
var key by remember { mutableStateOf (1) }
The above is crucial for it to work. The code is working as expected. Here's the details.
When you run this simple code block
var key by remember { mutableStateOf(1) }
LaunchedEffect(key) {
Log.e("xx", "Running key $key")
delay(2000)
key = 2
}
key = 3
The code runs as: key is initialized to 1, and the effect runs for the value of key = 1
, but, as correctly (I hope) pointed out by the OP in the comment below, LaunchedEffect
takes a bit of a time to spawn a coroutine, which is enough for the control to shift to the next statement and alter the value of the key to be 3. This ensures that the value of key as 1 is never logged.
After this and a delay of two seconds, the value of the key changes to one, triggering an entire recomposition of the Composable, which means that the entire composable shall re-execute. Here's how that goes:
The key remains as 2, because we're using remember
LaunchedEffect gets called with a value of 2, but again, due to the coroutine-spawning time, the key is modified to be 3, WHICH, being different than 2, RE-TRIGGERS a recomposition, hence, never logging the 2, but only logging the 3, since that is what the value of key
is now. Again, the previous LaunchedEffect
is not cancelled, and when its two-second delay is over, it will switch the value to 2
again, which immediately shifts back to 3
because of this composition. Hence, you'll get logs of Running 3
consistently, with two logs occurring very close together in time, while the next on will be separated by a two-second interval.
This is what you get
17:28:43.241 : Running key 3
17:28:43.269 : Running key 3
17:28:45.298 : Running key 3
17:28:45.318 : Running key 3
17:28:47.356 : Running key 3
17:28:47.374 : Running key 3
17:28:49.422 : Running key 3
17:28:49.443 : Running key 3
17:28:51.501 : Running key 3
17:28:51.534 : Running key 3
17:28:53.591 : Running key 3
17:28:53.607 : Running key 3
17:28:55.649 : Running key 3
17:28:55.689 : Running key 3
Now, if you wish to correctly log the value with which the effect was called, you need to store it at the entry point itself. Like so,
var key by remember { mutableStateOf(1) }
var keyStore: Int
LaunchedEffect(key.also { keyStore = key }) {
"Running key $keyStore".log()
delay(2000)
key = 2
}
key = 3
This produces the correct runtime logs
17:34:13.790 : Running key 1
17:34:13.821 : Running key 3
17:34:15.847 : Running key 2
17:34:15.862 : Running key 3
17:34:17.903 : Running key 2
17:34:17.922 : Running key 3
17:34:19.982 : Running key 2
17:34:20.015 : Running key 3
17:34:22.055 : Running key 2
17:34:22.073 : Running key 3
17:34:24.135 : Running key 2
17:34:24.154 : Running key 3
Upvotes: 2