jetpack compose 中的“组合”到底意味着什么

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

我试图了解 jetpack compose 中可组合项的生命周期。它写在文档中:

可组合项的生命周期由以下事件定义:进入组合、重组 0 次或多次以及离开组合。

但是我不太明白进入和离开作文的意义。我们是否可以粗略地假设在任何时刻,屏幕上显示的每个可组合项都“在组合中”?让我用文档中的示例来解释它。考虑以下代码片段:

@Composable
fun LoginScreen(showError: Boolean) {
if (showError) {
    LoginError()
}
LoginInput()
}

@Composable
fun LoginInput() { /* ... */ }

@Composable
fun LoginError() { /* ... */ }

如果我们将

false
传递给
LoginScreen()
,那么
LoginError()
就超出了构图吗?如果状态发生变化并且我们将
true
传递给
LoginScreen()
将会
LoginError()
进入合成吗?

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

组合可以描述为组合树的节点是如何构造的。它们也不一定是 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

https://stackoverflow.com/a/73181512/5457853

https://stackoverflow.com/a/77007725/5457853

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