导读大纲
1.1 了解 Jetpack Compose 中的状态
-
在 Jetpack Compose 的世界里
- 状态是动态交互式 UI 的核心和灵魂
- 它代表着影响用户界面在任何特定时刻的外观和行为的数据或值.
-
状态可以包括以下内容
- 用户输入
- 在文本字段中输入文本,切换复选框,调整滑块
- 来自网络请求的数据
- 从API接口或数据库获取的信息
- 应用程序内部数据
- 控制UI元素的变量或对象
- UI配置
- 影响 UI 外观的设置
- 用户输入
1.1.1 作为函数的可组合元素的状态
-
在 Jetpack Compose 中,UI是使用可组合函数构建的
- 这些函数不仅仅是描述用户界面外观的代码,它们还是其状态的函数
- 这意味着,可组合函数的输出(它所渲染的用户界面)
- 是由它所依赖的状态变量的当前值决定的
-
每当状态发生变化时,Jetpack Compose 就会重新执行相关的可组合函数
- 以便在用户界面中反映出这些变化,这个过程被称为重新组合
- 重新组合是一种机制,它允许 UI 根据状态变化进行动态更新
- 从而使用户界面具有交互性,并对用户操作做出响应
1.1.2 单向数据流
-
Jetpack Compose 采用单向数据流模型进行状态管理
-
这意味着状态通常是单向流动的:
- 向下流动
- 状态从父可组合元素向下流动到子可组合元素
- 父组件将状态值作为参数传递给子组件
- 向上流动
- 事件(如按钮点击或文本输入)从子组件向上流动到父组件
- 子组件发出事件,父组件通过修改状态来处理这些事件
- 然后触发重新组合(recomposition)
- 向下流动
-
这种单向流有助于保持清晰的关注点分离,使代码更易于推理和调试
- 它还能确保UI与最新状态保持一致,防止出现意想不到的副作用或不一致
-
例如, 考虑用一个简单的可组合函数来显示一个计数器
- <1> count 决定显示值的状态
- <2> onIncrement 是一个事件处理程序
- 当按钮被点击时,该事件处理程序将流向父组件
- 父组件将负责保持和更新 count 状态,并将其下传给Counter组件
@Composable
fun Counter(count: Int, onIncrement: () -> Unit) {
Column {
Text("Count: $count") // <1>
Button(onClick = onIncrement) { // <2>
Text("Increment")
}
}
}
- 通过了解状态的作用和单向数据流的概念
- 您将能够在 Jetpack Compose 中构建强大的交互式用户界面
1.2 状态的重要性
- 状态是交互式用户界面的生命线
- 使 Jetpack Compose UI能够动态地响应
- 用户操作、获取和显示数据并适应不断变化的条件
- 状态是如何在打造引人入胜的用户友好体验中发挥关键作用的
- 使 Jetpack Compose UI能够动态地响应
1.2.1 动态和响应式用户界面
-
如果没有状态,用户界面将是一幅静态图像
- 无法对用户做出反应,也无法反映 app 数据的变化
-
状态可让您构建具有以下功能的用户界面
- 响应用户输入
- 状态变量可以存储
- 来自文本字段、复选框、单选按钮和其他输入元素的值
- 当用户与这些元素交互时,状态会发生变化
- 从而触发重新组合并更新用户界面,以反映新的输入
- 状态变量可以存储
- 显示数据
- 状态可保存从网络请求、本地数据库或其他来源获取的数据
- 这些数据随后会显示在用户界面中
- 数据的任何更新都会自动刷新相应的UI元素
- 适应条件
- 状态可用于表示应用程序或其组件的内部状态
- 例如,一个布尔状态变量可以跟踪加载指示器是否应该可见
- 或者一个枚举变量可以表示导航流中的当前屏幕
- 响应用户输入
1.2.2 状态驱动的交互实例
-
只是尝鲜版示例,不用在意实现细节,后面会详细解析代码中涉及的盲点,比如
- remember 用于缓存历史状态值
- mutableStateOf 用于保存可变状态值
- by 这个其实是kotlin的语言特性,即委托属性
-
切换可见性
- showImage 状态变量控制图像组件是否可见
- 点击按钮会切换该状态, 触发重新组合并更新UI
- showImage 状态变量控制图像组件是否可见
@Composable
fun MyComposable() {
var showImage by remember { mutableStateOf(false) }
Column {
Button(onClick = { showImage = !showImage }) {
Text(if (showImage) "Hide Image" else "Show Image")
}
if (showImage) {
Image(painterResource(id = R.drawable.my_image), contentDescription = "My Image")
}
}
}
- 更新文本内容
- text状态变量存储来自 TextField 的输入内容
- UI会实时更新以显示输入的文本
- text状态变量存储来自 TextField 的输入内容
@Composable
fun MyComposable() {
var text by remember { mutableStateOf("Hello") }
Column {
TextField(value = text, onValueChange = { text = it }) // Update 'text' on change
Text("You entered: $text")
}
}
- 改变颜色
- isRed 状态变量决定按钮的颜色
- 点击按钮会切换状态并更新按钮颜色
- isRed 状态变量决定按钮的颜色
@Composable
fun MyComposable() {
var isRed by remember { mutableStateOf(false) }
val buttonColor = if (isRed) Color.Red else Color.Blue
Button(
onClick = { isRed = !isRed },
colors = ButtonDefaults.buttonColors(
containerColor = buttonColor
)
) {
Text("Change Color")
}
}