首页 Android 正文
  • 本文约3386字,阅读需17分钟
  • 51
  • 0

了解 Jetpack Compose 中的重组

摘要

Jetpack Compose通过使 Android UI 具有声明性和响应性,彻底改变了我们构建 Android UI 的方式。 Compose 中最重要的概念之一是重组。这个概念对于理解 UI 元素如何有效更新以响应状态变化至关重要。在本文中,将探讨什么是重组、它在 Jetpack Compose 中的工作原理,并提供示例来演示其行为。 什么是重组? 在...

Jetpack Compose通过使 Android UI 具有声明性和响应性,彻底改变了我们构建 Android UI 的方式。 Compose 中最重要的概念之一是重组。这个概念对于理解 UI 元素如何有效更新以响应状态变化至关重要。在本文中,将探讨什么是重组、它在 Jetpack Compose 中的工作原理,并提供示例来演示其行为。

什么是重组?

在 Jetpack Compose 中,UI 是使用称为composables 的函数构建的。这些函数将数据作为输入并根据该数据发出 UI 元素。当可组合项的输入数据(或状态)发生更改时,Compose 会自动重新计算(或“重新组合”)可组合项以反映新状态。这个过程称为重组(recomposition)。

每当可组合函数读取的状态发生变化时,都会发生重组。 Jetpack Compose 无需重新绘制整个 UI,而是仅高效地重新执行那些需要更新的可组合项,从而提高性能。

重组的要点

• 重组是由状态变化触发的。
• Compose 尝试通过仅重新执行受更改影响的 UI 部分来优化重组过程。
• 如果输入数据未更改,则不会发生这种情况。
• 重组是声明性的:您根据状态描述所需的 UI,Compose 在状态更改时更新它。

示例:了解State重组

通过一个示例来说明 Jetpack Compose 中的重组。

@Composable
fun Counter() {
    // 'count' is the state that controls recomposition
    var count by remember { mutableStateOf(0) }

    // The Text and Button composables will be recomposed every time 'count' changes
    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier.fillMaxSize()
    ) {
        // Display the current count
        Text(text = "Count: $count", fontSize = 24.sp)

        // Button that increments the count on click
        Button(onClick = { count++ }) {
            Text("Increment")
        }
    }
}

解释:

  1. mutableStateOf(0) :我们使用mutableStateOf创建状态变量count 。这是 Compose 中的一种特殊类型的状态,当状态发生变化时可以触发重组。
  2. Text和Button :这些是依赖于count状态的可组合项。 Text可组合项将显示count的值,而Button允许用户增加它。
  3. 重新组合:每次单击按钮并且count增加时,可组合项都会重新组合,更新 UI 以反映新的计数。

示例:最小化不必要的重组

有时,如果 UI 的某些部分所依赖的状态未更改,如果要避免重新组合。 Compose 通过确保仅重组相关部分来优化重组。

@Composable
fun CounterWithStaticText() {
    var count by remember { mutableStateOf(0) }

    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier.fillMaxSize()
    ) {
        // This part will not recompose, as it does not depend on 'count'
        StaticText()

        // This part will recompose when 'count' changes
        Text(text = "Count: $count", fontSize = 24.sp)
        Button(onClick = { count++ }) {
            Text("Increment")
        }
    }
}

@Composable
fun StaticText() {
    Text("This text does not change.", fontSize = 18.sp)
}

解释:

StaticText可组合项不依赖于任何状态,因此当count更改时它不会被重新组合。只有显示计数的Text和按钮才会重新组合。

这演示了如何在发生不相关的状态更改时防止 UI 的静态部分进行不必要的重组。

使用rememberrememberSaveable

Compose 中的remember函数用于存储在重组后仍能保存的值。如果没有它,每次重构函数时都会重置状态。

@Composable
fun RememberCounter() {
    // 'remember' ensures that 'count' survives recompositions
    var count by remember { mutableStateOf(0) }

    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier.fillMaxSize()
    ) {
        Text(text = "Remembered Count: $count", fontSize = 24.sp)
        Button(onClick = { count++ }) {
            Text("Increment")
        }
    }
}

使用remember , count在重组之间保留其值。这对于存储与 UI 相关的状态非常有用,并且不应每次都重置。

如果想在配置更改时保存状态(例如屏幕旋转),可以使用rememberSaveable

@Composable
fun SaveableCounter() {
    // 'rememberSaveable' saves state across configuration changes
    var count by rememberSaveable { mutableStateOf(0) }

    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier.fillMaxSize()
    ) {
        Text(text = "Saveable Count: $count", fontSize = 24.sp)
        Button(onClick = { count++ }) {
            Text("Increment")
        }
    }
}

示例:使用 Kotlin 协程流进行重组

Kotlin 的Flow通常用于观察数据的变化,可以将其与 Compose 结合起来进行响应式 UI 更新。下面是一个示例,其中使用Flow发出在 Compose 中触发重组的值。

@Composable
fun CounterWithFlow() {
    // Create a Flow that emits incremented values every second
    val counterFlow = flow {
        var counter = 0
        while (true) {
            delay(1000L)
            emit(counter++)
        }
    }

    // Collect the flow and use it to display the counter
    val counter by counterFlow.collectAsState(initial = 0)

    Text(text = "Counter: $counter", fontSize = 24.sp)
}

解释:

• 定义一个每秒发出一个新计数器值的Flow 。
• collectAsState()收集Flow并在每次发出新值时触发重组。
• UI 会自动更新以显示计数器的最新值,无需显式 UI 更新。

重组什么时候发生?

  1. 当可组合函数中使用的状态发生变化时(例如,当更新mutableStateOf时)。
  2. 当Flow 、 LiveData或StateFlow中的状态发生更改并收集在可组合项中时。
  3. 当父可组合项被重组时,其子项也可能会重组,具体取决于它们是否依赖于已更改的状态。

结论

Jetpack Compose 中的重组是一个强大的概念,可确保您的 UI 对状态更改保持反应。它使 UI 变得动态并消除了手动更新的需要。通过使用rememberrememberSaveable和 Kotlin Coroutines Flow等工具,可以有效地管理重组并创建响应灵敏且流畅的 UI。

使用 Jetpack Compose 构建更复杂的应用程序时,了解重组对于优化性能和确保流畅的用户体验至关重要。 Compose 的声明性性质能编写更简单、更直观的 UI 代码


扫描二维码,在手机上阅读


    评论