Jetpack Compose 状态

状态 State

kotlin 复制代码
// Don't copy over
@Composable
private fun Greeting(name: String) {
    var expanded = false // Don't do this!

    Surface(
        color = MaterialTheme.colorScheme.primary,
        modifier = Modifier.padding(vertical = 4.dp, horizontal = 8.dp)
    ) {
        Row(modifier = Modifier.padding(24.dp)) {
            Column(modifier = Modifier.weight(1f)) {
                Text(text = "Hello, ")
                Text(text = name)
            }
            ElevatedButton(
                onClick = { expanded = !expanded }
            ) {
                Text(if (expanded) "Show less" else "Show more")
            }
        }
    }
}

通过点击 Button 切换按钮文本内容,定义了临时变量 expanded,点击时修改;这种写法在 Compose 无法发挥作用;

原因:普通变量 expanded 设置不同的值不会使 Compose 将其检测为状态更改,因此不会产生任何效果。

重组 :数据发生变化,Compose 会使用新数据重新执行这些函数,从而创建更新后的界面,此过程称为~

Compose 还会查看各个可组合项需要哪些数据,以便只需重组数据发生了变化的组件,而避免重组未受影响的组件。

State / MutableState

如需向可组合项添加内部状态,可以使用 mutableStateOf 函数,该函数可让 Compose 重组读取该 State 的函数。

StateMutableState 是两个接口,它们具有特定的值,每当该值发生变化时,它们就会触发界面更新(重组)。

解决:使用 mutableStateOf 后如下

kotlin 复制代码
import androidx.compose.runtime.mutableStateOf
...

// Don't copy over
@Composable
fun Greeting() {
    val expanded = mutableStateOf(false) // Don't do this!
    Log.e("tag", "expanded = ${expanded.value}")
    ... 
}

点击按钮后,触发了重组,界面刷新了(log 会在点击按钮后打印),但按钮内容依然没变;

原因:每次调用 Greeting 时,都会将该变量重置为 false。

解决:如需在重组后保留状态,请使用 remember 记住可变状态。

Remember

remember 是记录数据,防止状态在重组时被重置;

至此:点击按钮变化文案的功能完毕了,修改后的代码如下

kotlin 复制代码
@Composable
private fun Greeting(name: String) {
    // 记录数据
    val expanded = remember { mutableStateOf(false) }

    Surface(
        color = MaterialTheme.colorScheme.primary,
        modifier = Modifier.padding(vertical = 4.dp, horizontal = 8.dp)
    ) {
        Row(modifier = Modifier.padding(24.dp)) {
            Column(modifier = Modifier.weight(1f)) {
                Text(text = "Hello, ")
                Text(text = name)
            }
            ElevatedButton(
                onClick = { expanded.value = !expanded.value }
            ) {
                Text(if (expanded.value) "Show less" else "Show more")
            }
        }
    }
}

声明 MutableState 对象的三种方式:

  • val mutableState = remember { mutableStateOf(default) }
  • var value by remember { mutableStateOf(default) }
  • val (value, setValue) = remember { mutableStateOf(default) }

by 委托语法需要以下导入:

kotlin 复制代码
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue

状态提升

无状态可组合项是指不保持任何状态的可组合项

Compose 中的状态提升是一种将状态移至可组合项的调用方以使可组合项无状态的模式

  • 单一可信来源:通过移动状态,而不是复制状态,我们可确保只有一个可信来源。这有助于避免 bug。
  • 封装:只有有状态可组合项能够修改其状态。这完全是内部的。
  • 可共享 :可与多个可组合项共享提升的状态。如果您想在另一个可组合项中读取 name,可以通过变量提升来做到这一点。
  • 可拦截:无状态可组合项的调用方可以在更改状态之前决定忽略或修改事件。
  • 解耦 :无状态 ExpandingCard 的状态可以存储在任何位置
kotlin 复制代码
@Composable
fun HelloScreen() {
    var name by rememberSaveable { mutableStateOf("") }

    HelloContent(name = name, onNameChange = { name = it })
}

@Composable
fun HelloContent(name: String, onNameChange: (String) -> Unit) {
    Column(modifier = Modifier.padding(16.dp)) {
        Text(
            text = "Hello, $name",
            modifier = Modifier.padding(bottom = 8.dp),
            style = MaterialTheme.typography.h5
        )
        OutlinedTextField(
            value = name,
            onValueChange = onNameChange,
            label = { Text("Name") }
        )
    }
}

状态提升规则:

  1. 状态应至少提升到使用该状态(读取)的所有可组合项的最低共同父项
  2. 状态应至少提升到它可以发生变化(写入)的最高级别
  3. 如果两种状态发生变化以响应相同的事件 ,它们应一起提升

LazyListState

官方文档解释: A state object that can be hoisted to control and observe scrolling.

文章参考:Compose 中的状态

相关推荐
崔庆才丨静觅4 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60615 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了5 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅5 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅6 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅6 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment6 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅7 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊7 小时前
jwt介绍
前端
爱敲代码的小鱼7 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax