kotlin 为什么我的MutableState值在LaunchedEffect中重置

yqlxgs2m  于 2023-02-09  发布在  Kotlin
关注(0)|答案(1)|浏览(149)

我正在尝试用Kotlinjetpack compose学习android编程,并且正在制作一个聊天应用程序。但是,在按下发送按钮后,我似乎无法传递我的TextField值。
我使用了一个自定义的可点击函数,定义如下:

@Composable
fun Modifier.timedClick(
    timeInMillis: Long = 2500,
    defaultPercentage: Float = 0f,
    content: String = "",
    onClick: (Float, String) -> Unit,
    interactionSource: MutableInteractionSource = remember{MutableInteractionSource()}
) = composed{
    var timeOfTouch = -1L
    Log.d("BUTTON", "#1 The content before LaunchedEffect is: $content")
    LaunchedEffect(interactionSource){
        Log.d("BUTTON", "#2 The content before LaunchedEffect is: $content")
        interactionSource.interactions.onEach {
            when(it){
                is PressInteraction.Press ->{
                    timeOfTouch = System.currentTimeMillis()
                    Log.d("BUTTON", "#3 The content after button pressed is: ${content}")
                    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)
                    onClick(min(calculatedPercentage, 1f),
                        content
                    )
                    Log.d("BUTTON", "#4 The content after button is released is: ${content}")
                    Log.d("BUTTON", "the button has been released, the calculated percentage is ${calculatedPercentage * 100}% and the time is ${(currentTime-timeOfTouch).toFloat()/timeInMillis}ms")
                }
                is PressInteraction.Cancel -> {
                    timeOfTouch = -1L
                }
            }
        }
            .launchIn(this)
    }
    Modifier.clickable (
        interactionSource = interactionSource,
        indication = rememberRipple(),
        onClick = {}
    )

}

然后使用图像作为按钮并传递文本字段值,如下所示

var textFieldValue by remember { mutableStateOf("") }
        TextField(
            value = textFieldValue,
            onValueChange = { textFieldValue = it },
            modifier = Modifier.fillMaxWidth()
        )
        Box(modifier = Modifier
            .fillMaxWidth()
            .fillMaxHeight()){
            Image(
                modifier = Modifier
                    .clip(CircleShape)
                    .size(70.dp)
                    .align(Alignment.Center)
                    .timedClick(
                        content = textFieldValue,
                        onClick = onClick
                    ),
                contentDescription = null,
                painter = painterResource(id = R.drawable.poop3),
                contentScale = ContentScale.Crop
            )
        }

但是,每次我发送时,LaunchedEffect中的content变量总是空的(例如,在log.d #1中,内容会定期正确地更新,但log.d #2只在运行开始时调用一次,log.d #3和#4总是显示空字符串。

vmdwslir

vmdwslir1#

Launched效果中的内容为空的原因是因为您在使用状态值初始化timedClick函数时它为空。您可以通过将状态作为参数而不是值传递来修复此问题。
为此,您必须在创建textFieldValue变量时将by替换为=

val textFieldValue = remember { mutableStateOf("") }
TextField(
   value = textFieldValue.value,
   onValueChange = { textFieldValue.value = it },
   modifier = Modifier.fillMaxWidth()
 )

必须将timedClick函数更改为以下内容:

@Composable
fun Modifier.timedClick(
    timeInMillis: Long = 2500,
    defaultPercentage: Float = 0f,
    content: MutableState<String>,
    onClick: (Float, String) -> Unit,
    interactionSource: MutableInteractionSource = remember{MutableInteractionSource()}
) = composed{
    var timeOfTouch = -1L
    Log.d("BUTTON", "#1 The content before LaunchedEffect is: ${content.value}")
    LaunchedEffect(interactionSource) {
        Log.d("BUTTON", "#2 The content before LaunchedEffect is: ${content.value}")
        interactionSource.interactions.onEach {
            when(it){
                is PressInteraction.Press ->{
                    timeOfTouch = System.currentTimeMillis()
                    Log.d("BUTTON", "#3 The content after button pressed is: ${content.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)
                    onClick(min(calculatedPercentage, 1f),
                        content.value
                    )
                    Log.d("BUTTON", "#4 The content after button is released is: ${content.value}")
                    Log.d("BUTTON", "the button has been released, the calculated percentage is ${calculatedPercentage * 100}% and the time is ${(currentTime-timeOfTouch).toFloat()/timeInMillis}ms")
                }
                is PressInteraction.Cancel -> {
                    timeOfTouch = -1L
                }
            }
        }
            .launchIn(this)
    }
    Modifier.clickable (
        interactionSource = interactionSource,
        indication = rememberRipple(),
        onClick = {}
    )
}

EDIT:当你把状态作为参数传递时,它将传递一个对存储状态的内存位置的引用。当你在文本域中键入时,这个位置中的值将被更新。这就是为什么更新的内容将在timedClick函数中可用。

相关问题