我试图了解 jetpack compose 中可组合项的生命周期。它写在文档中:
可组合项的生命周期由以下事件定义:进入组合、重组 0 次或多次以及离开组合。
但是我不太明白进入和离开作文的意义。我们是否可以粗略地假设在任何时刻,屏幕上显示的每个可组合项都“在组合中”?让我用文档中的示例来解释它。考虑以下代码片段:
@Composable
fun LoginScreen(showError: Boolean) {
if (showError) {
LoginError()
}
LoginInput()
}
@Composable
fun LoginInput() { /* ... */ }
@Composable
fun LoginError() { /* ... */ }
如果我们将
false
传递给 LoginScreen()
,那么 LoginError()
就超出了构图吗?如果状态发生变化并且我们将 true
传递给 LoginScreen()
将会 LoginError()
进入合成吗?
组合可以描述为组合树的节点是如何构造的。它们也不一定是 ui 可组合项,也不必在屏幕上绘制作为组合的一部分。
你的例子是正确的,任何条件语句都可以改变它在重组时的结构。
Composition 是可组合项第一次在组合树中发生,当读取任何
State
时,该可组合项的范围的任何部分或整个可组合项都会更新为新值,基于其他一些因素,它可能会更新为相同的值以及诸如 SnapshotMutationPolicy 或 Composable 的稳定性,这是recomposition
。当某些逻辑从树中删除可组合项时,可组合项会留下组合。
DisposableEffect 函数是一个非 ui 可组合项,您可以在可组合项进入或退出合成时跟踪它。
在下面的示例中,当计数器为 3 时,Text 和 DisposableEffect 进入重组,保持组合状态,并且 Text 使用新的计数器值重组,直到 6,当达到 6 DisposableEffect 时,Text 离开组合
@Preview
@Composable
private fun NonUIComposableSample() {
val context = LocalContext.current
var counter by remember { mutableStateOf(0) }
if (counter in 3..5) {
Text("Counter: $counter")
DisposableEffect(Unit){
Toast.makeText(context, "enter recomposition $counter", Toast.LENGTH_SHORT).show()
onDispose {
Toast.makeText(context, "exit recomposition $counter", Toast.LENGTH_SHORT).show()
}
}
}
Button(onClick = { counter++ }) {
Text("Counter: $counter")
}
}
并且输入、重组、离开组合生命周期也不需要 ui 可组合。
@Composable
private fun NonUIComposableSample() {
val context = LocalContext.current
var counter by remember { mutableStateOf(0) }
var color by remember { mutableStateOf(Color.Red) }
if (counter in 3..5) {
DisposableEffect(Unit) {
Toast.makeText(context, "Entering Composition counter: $counter", Toast.LENGTH_SHORT).show()
color = Color.Yellow
onDispose {
color = Color.Green
Toast.makeText(context, "Exiting Composition counter: $counter", Toast.LENGTH_SHORT).show()
}
}
}
Button(onClick = { counter++ }) {
Text("Counter: $counter", color = color)
}
}
对于 Ui 可组合性来说,除了组合之外还有三个阶段,这三个阶段在深度上被调用。
Compose 分为三个主要阶段:
Composition:显示什么 UI。 Compose 运行可组合函数并创建 UI 的描述。 Layout:放置 UI 的位置。此阶段包括两个步骤:测量和放置。对于布局树中的每个节点,布局元素测量并放置其自身以及任何子元素在 2D 坐标中。 绘图:它是如何渲染的。 UI 元素绘制到 Canvas 中,通常是设备屏幕。
即使 Composasble 的大小为 0.dp 或未在屏幕上绘制(如果您指定 Modifier.drawWithContent{} 不绘制内容),或者即使它未放置(如果您不在放置范围内调用 place),它仍然可能是组合树的一部分,意味着它是组合的。
假设您有像下面这样的 ui 树
Column() {
println("Parent Scope")
Column() {
println("Child1 Outer Scope")
Text("Child1 Outer Content")
Column() {
println("Child1 Inner Scope")
Text("Child1 Inner Content")
}
}
Column() {
println("Child2 Scope")
Text("Child2 Content")
}
}
Parent Layout
/ \
/ \
/ \
/ \
Child1 外部 Child2 | 儿童1内
打印
I Parent Scope
I Child1 Outer Scope
I Child1 Inner Scope
I Child2 Scope
这是组合发生的顺序,从左侧开始树,直到内部子节点,进入下一个分支,依此类推。然后在布局阶段,首先测量 child1 Inner,Child1 Outer,Child2,然后使用来自 child 的信息测量 Parent,并且它们以相同的顺序进行组合发生。
您也可以参考这个答案
https://stackoverflow.com/a/73181512/5457853