英文:
How does Jetpack Compose detect change in variable for recomposition
问题
Compose使用mutableStateOf
来追踪result
的变化。当result
的值在Button
的onClick
回调函数内被更新时,mutableStateOf
会通知Compose框架有状态变化发生,从而触发重新组合(recomposition)。这不是通过Image
的painter
参数或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
)
将相同的函数应用于 Button
和 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")
}
}
请注意,在此示例中,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")
}
}
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论