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 中的状态

相关推荐
天若有情67312 小时前
新闻通稿 | 软件产业迈入“智能重构”新纪元:自主进化、人机共生与责任挑战并存
服务器·前端·后端·重构·开发·资讯·新闻
香香爱编程13 小时前
electron对于图片/视频无法加载的问题
前端·javascript·vue.js·chrome·vscode·electron·npm
程序猿_极客13 小时前
【期末网页设计作业】HTML+CSS+JavaScript 蜡笔小新 动漫主题网站设计与实现(附源码)
前端·javascript·css·html·课程设计·期末网页设计
zl_vslam13 小时前
SLAM中的非线性优-3D图优化之轴角在Opencv-PNP中的应用(一)
前端·人工智能·算法·计算机视觉·slam se2 非线性优化
CDwenhuohuo14 小时前
用spark-md5实现切片上传前端起node模拟上传文件大小,消耗时间
前端
阿桂有点桂14 小时前
React使用笔记(持续更新中)
前端·javascript·react.js·react
自由日记14 小时前
实例:跳动的心,火柴人
前端·css·css3
柯腾啊14 小时前
一文简单入门 Axios
前端·axios·apifox
im_AMBER14 小时前
React 15
前端·javascript·笔记·学习·react.js·前端框架
How_doyou_do15 小时前
模态框的两种管理思路
java·服务器·前端