为什么带有 onClick lambda 的按钮每次点击都会重组两次?

问题描述 投票:0回答:1

为什么按钮每次点击都会重新组合两次?

代码片段:

var counter by remember { mutableIntStateOf(0) }
Button(onClick = { counter++ }) {
  Text(text = "I've been clicked $counter times")
}

观察:

当单击按钮 x 次时,根据布局检查器,可以看到按钮已重组 2 次。 Button is recomposed 6 times, when button is clicked thrice.

android-jetpack-compose
1个回答
0
投票

由于海拔变化,在实现

Surface
时,
Button
会发生重组。而且往往是点击次数的两倍以上。如果您将手指按住按钮并松开,您也可以在松开后观察重组。

Material库的Button源代码,我只注释了elevation以将其传递给SideEffect。

@Composable
fun MyButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource? = null,
    elevation: ButtonElevation? = ButtonDefaults.elevation(),
    shape: Shape = MaterialTheme.shapes.small,
    border: BorderStroke? = null,
    colors: ButtonColors = ButtonDefaults.buttonColors(),
    contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
    content: @Composable RowScope.() -> Unit
) {
    @Suppress("NAME_SHADOWING")
    val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
    val contentColor by colors.contentColor(enabled)

    val elevationValue = elevation?.elevation(enabled, interactionSource)?.value ?: 0.dp

    SideEffect {
        println("Recomposing... $elevationValue")
    }

    Surface(
        onClick = onClick,
        modifier = modifier.semantics { role = Role.Button },
        enabled = enabled,
        shape = shape,
        color = colors.backgroundColor(enabled).value,
        contentColor = contentColor.copy(alpha = 1f),
        border = border,
        elevation = elevationValue,
//        elevation = elevation?.elevation(enabled, interactionSource)?.value ?: 0.dp,
        interactionSource = interactionSource
    ) {
        CompositionLocalProvider(LocalContentAlpha provides contentColor.alpha) {
            ProvideTextStyle(
                value = MaterialTheme.typography.button
            ) {
                Row(
                    Modifier
                        .defaultMinSize(
                            minWidth = ButtonDefaults.MinWidth,
                            minHeight = ButtonDefaults.MinHeight
                        )
                        .padding(contentPadding),
                    horizontalArrangement = Arrangement.Center,
                    verticalAlignment = Alignment.CenterVertically,
                    content = content
                )
            }
        }
    }
}

您可以观察

SideEffect
中的值变化。如果您评论海拔,您将不会看到额外的重组。

© www.soinside.com 2019 - 2024. All rights reserved.