Jetpack Compose中LaunchedEffect内MutableState值重置问题求助
问题原因
你的问题出在LaunchedEffect的依赖项和变量捕获机制上:
LaunchedEffect(interactionSource)仅在interactionSource变化时重新启动,content参数更新不会触发它重组。- LaunchedEffect内部会捕获初始化时的
content值,之后即使外部content(即TextField的输入值)更新,内部的content变量仍保持首次启动时的空字符串,这就是日志#3、#4始终为空的原因。 - 日志#1位于
composed块内,每次Compose重组(比如TextField输入变化)都会执行,所以能显示最新的content;而日志#2仅在LaunchedEffect首次启动时执行一次,因此只显示初始空值。
解决方案
使用 rememberUpdatedState 包装 content 参数,它能在不重启LaunchedEffect的前提下,让我们获取到最新的 content 值。修改后的完整代码如下:
@Composable fun Modifier.timedClick( timeInMillis: Long = 2500, defaultPercentage: Float = 0f, content: String = "", onClick: (Float, String) -> Unit, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() } ) = composed { var timeOfTouch = -1L // 用rememberUpdatedState跟踪最新的content值 val latestContent = rememberUpdatedState(content) Log.d("BUTTON", "#1 The content before LaunchedEffect is: $content") LaunchedEffect(interactionSource) { Log.d("BUTTON", "#2 The content when LaunchedEffect starts is: ${latestContent.value}") interactionSource.interactions.onEach { when (it) { is PressInteraction.Press -> { timeOfTouch = System.currentTimeMillis() Log.d("BUTTON", "#3 The content after button pressed is: ${latestContent.value}") Log.d("BUTTON", "the button has been pressed") } is PressInteraction.Release -> { val currentTime = System.currentTimeMillis() val calculatedPercentage: Float = defaultPercentage + ((currentTime - timeOfTouch).toFloat() / timeInMillis) * (1 - defaultPercentage) // 使用latestContent.value传递最新值 onClick(min(calculatedPercentage, 1f), latestContent.value) Log.d("BUTTON", "#4 The content after button is released is: ${latestContent.value}") Log.d("BUTTON", "the button has been released, the calculated percentage is ${calculatedPercentage * 100}% and the duration is ${(currentTime - timeOfTouch)}ms") } is PressInteraction.Cancel -> { timeOfTouch = -1L } } }.launchIn(this) } Modifier.clickable( interactionSource = interactionSource, indication = rememberRipple(), onClick = {} ) }
关键说明
rememberUpdatedState会在content参数变化时自动更新其内部的value,但不会触发LaunchedEffect重启,既保证能获取最新输入值,又不会中断用户正在进行的长按交互。- LaunchedEffect内部所有需要使用
content的地方,都替换为latestContent.value,确保拿到实时的TextField输入值。
内容的提问来源于stack exchange,提问作者Justice Gabriel Antaputra
相关产品推荐
相关产品推荐

