Just wanted to clarify whether my understanding of...
# compose
i
Just wanted to clarify whether my understanding of LaunchedEffect and rememberUpdatedState is correct. This is an example from Android developer site @Composable fun NotificationHost(state: NotificationState, onTimeout: (Notification) -> Unit) { val currentOnTimeout by rememberUpdatedState(onTimeout) state.currentNotification?.let { currentNotification -> LaunchedEffect(currentNotification) { // We should not restart this delay if onTimeout changes, but we want to call // the onTimeout we were last recomposed with when it completes. delay(NotificationTimeout) currentOnTimeout(currentNotification) } } // ... } -- LaunchedEffect will be executed during initial composition. -- And after that the effect will only run if the effect's parameters change. -- Sometimes the effect refers a value or event callback in its code block which is not passed as a parameter to the effect.( We don't want to restart the effect when the value or the event callback changes) . But we need to remember them during recomposition. Also they need to be updated with the new value or callback during recomposition. So we use rememberUpdatedState. This way if the effect is relaunched when one of its key is updated it will get the updated value or callback which is referred in the effect. -- LaunchedEffect will survive recompositions Thanks
👍 1
l
Hey, you’re correct. LaunchedEffect will get triggered on the first composition and it gets cancelled only when it leaves the composition, or when the subject changes - then it would get re-launched
i
Thanks.. any comments regarding rememberUpdatedState...
a
This way if the effect is relaunched when one of its key is updated it will get the updated value or callback which is referred in the effect.
You will always get the latest value when you read the state. This has nothing to do with whether the effect is relaunched or not.
If you read the source of
rememberUpdatedState
you'll see that it's simply
remember { mutableStateOf(newValue) }.apply { value = newValue }
.
i
Thanks... Then why don't we simply use remember { mutableStateOf(value) }... Probably there might be couple of nuances to remberUpdatedState.. I will check that..
a
It's a convenience method.
i
Oh ok... I get it.... Thank you..
z
It also makes your intent more obvious - it’s more obvious to someone reading this code that you’re planning to use this value from somewhere that outlives the composition later.
And one thing to note re: LaunchedEffect - it will not be executed during the initial composition - it will be executed once the initial composition is committed. That means it won’t execute until some time after your composable function returns, and won’t be executed at all if the composition fails for some reason (eg your function throws an exception later on).
a
Please read the pinned message.
i
Thanks...will update the message...
Thanks...If a LaunchedEffect is running while the composable it's in is recomposed, the effect won't be restarted right... Code block from JetNews... OptIn(ExperimentalMaterialApi::class) @Composable fun HomeScreen( posts: UiState<List<Post>>, favorites: Set<String>, onToggleFavorite: (String) -> Unit, onRefreshPosts: () -> Unit, onErrorDismiss: () -> Unit, navigateTo: (Screen) -> Unit, scaffoldState: ScaffoldState ) { if (posts.hasError) { _*// If onRefreshPosts or onErrorDismiss change while the LaunchedEffect is running, // don't restart the effect and use the latest lambda values.*_ val onRefreshPostsState by rememberUpdatedState(onRefreshPosts) val onErrorDismissState by rememberUpdatedState(onErrorDismiss) LaunchedEffect(scaffoldState) { val snackbarResult = scaffoldState.snackbarHostState.showSnackbar( message = errorMessage, actionLabel = retryMessage ) when (snackbarResult) { SnackbarResult.ActionPerformed -> onRefreshPostsState() SnackbarResult.Dismissed -> onErrorDismissState() } } }
a
I don't understand your question.
LaunchedEffect
won't be restarted unless the keys change.