Jetpack Compose如何检测变量的更改以进行重新组合。

huangapple go评论85阅读模式
英文:

How does Jetpack Compose detect change in variable for recomposition

问题

Compose使用mutableStateOf来追踪result的变化。当result的值在ButtononClick回调函数内被更新时,mutableStateOf会通知Compose框架有状态变化发生,从而触发重新组合(recomposition)。这不是通过Imagepainter参数或remember来检测的,而是通过mutableStateOf和Compose框架内部的状态追踪机制来实现的。

英文:

I am doing a Google Codelab and have the following code (drawable changes when button is pressed):

@Composable
fun DiceWithButtonAndImage(modifier: Modifier = Modifier) {
    var result by remember { mutableStateOf(1) }
    val imageResource = when (result) {
        1 -> R.drawable.dice_1
        2 -> R.drawable.dice_2
        3 -> R.drawable.dice_3
        4 -> R.drawable.dice_4
        5 -> R.drawable.dice_5
        else -> R.drawable.dice_6
    }

    Column(
        modifier = modifier,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Image(painter = painterResource(imageResource), contentDescription = result.toString())

        Button(onClick = { result = (1..6).random() }) {
            Text(text = stringResource(R.string.roll_text))
        }
    }
}

How does Compose know that result has changed when it triggers recomposition? Does it detect that through Image's painter parameter? Or maybe through remember or mutableStateOf()?

答案1

得分: 3

The answer is in the documentation:

> mutableStateOf 创建一个可观察MutableState<T>,它是与 Compose 运行时集成的可观察类型。
对此值的任何更改都会安排重新组合任何读取该值的可组合函数。

在您的示例中,当您单击按钮时,result 会更改。imageResource 读取此值,它会触发最近范围内的重新组合。
由于 Column 是一个内联函数(这意味着 Column 没有自己的重新组合范围),因此 Column 的内容会重新组合。

您可以使用以下函数进行可视检查:

fun randomColor() = Color(
    Random.nextInt(256),
    Random.nextInt(256),
    Random.nextInt(256),
    alpha = 255
)

将相同的函数应用于 ButtonColumn 的背景颜色:

Column(
    modifier = Modifier.background(getRandomColor()),
    horizontalAlignment = Alignment.CenterHorizontally
) {
    Image(
        modifier = Modifier.background(getRandomColor()),
        painter = painterResource(R.drawable.ic_xxx),
        contentDescription = result.toString()
    )

    Button(
        onClick = { result = (1..6).random() },
        colors = ButtonDefaults.buttonColors(containerColor = getRandomColor())
    ) {
        Text(text = "Button")
    }
}

Jetpack Compose如何检测变量的更改以进行重新组合。

请注意,在此示例中,Image 使用的是静态资源而不是 imageResource

英文:

The answer is in the documentation:

> mutableStateOf creates an observable MutableState<T>, which is an observable type integrated with the compose runtime.
Any changes to this value schedules recomposition of any composable functions that read the value.

In your example when you click the button the result changes. imageResource reads this value and it triggers recomposition in nearest scope.
Since the Column is an inline function (it means that Column doesn't have an own recompose scopes) the content of the Column is recomposed.

You can check it visually using this function:

fun randomColor() = Color(
    Random.nextInt(256),
    Random.nextInt(256),
    Random.nextInt(256),
    alpha = 255
)

Apply the same function to the background color of the Button and the Column:

    Column(
        modifier = Modifier.background(getRandomColor()),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Image(
            modifier = Modifier.background(getRandomColor()),
            painter = painterResource(R.drawable.ic_xxx), contentDescription = result.toString())

        Button(onClick = { result = (1..6).random() },
                colors= ButtonDefaults.buttonColors(containerColor = getRandomColor()),) {
            Text(text = "Button")
        }
    }

Jetpack Compose如何检测变量的更改以进行重新组合。

Note that in this example the Image uses a static resource and not the imageResource.

答案2

得分: 1

这是翻译后的内容:

这个问题很难简洁地回答,以简化的形式来说 - Compose 使用快照系统来检测更改。它使用观察者模式来观察状态的变化。依赖于状态的代码部分会在状态注册更改监听器时被通知,当值发生变化时,所有已注册的监听器都会收到通知。

因此,在您的示例中,mutableStateOf(1) 会自动在Composer中创建监听器,并且 DiceWithButtonAndImage 函数会在每次状态更改时收到通知。

英文:

It is quite difficult to answer this question briefly, in a simplified form - Compose uses the Snapshot System to detect changes. It uses an observer pattern to observe changes to state. The parts of the code that depend on the state register change listeners, when the value changes, all registered listeners are notified.

So in your example mutableStateOf(1) automatically creates listener in Composer, and DiceWithButtonAndImage function gets notified on every sate change.

huangapple
  • 本文由 发表于 2023年5月14日 23:08:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76248186.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定