天天看点

Jetpack Compose 管理状态(一)

前言

Jetpack Compose 可帮助您明确状态在 Android 应用中的存储位置和使用方式,状态管理是使用 Compose 开发ui首要面临的问题。

Jetpack compose 引入新的开发范式 (MVI)

​​Jetpack Compose 架构比较:MVP & MVVM & MVI​​

应用中的状态是指可以随时间变化的任何值。这是一个非常宽泛的定义,从 Room 数据库到类的变量,全部涵盖在内。

所有 Android 应用都会向用户显示状态。下面是 Android 应用中的一些状态示例:

  1. 在无法建立网络连接时显示的信息提示控件。
  2. 博文和相关评论点赞背景变化,或者icon变化。
  3. 在用户点击按钮时播放的波纹动画。
状态和组合

由于 Compose 是​​声明式​​工具集,不能按照之前命令式手动进行界面ui刷新。更新它的唯一方法是通过新参数调用同一可组合项,这里需要引入状态控制。状态的更改会触发可组合函数进行重组。

@Composable
fun HelloContent() {
   Column(modifier = Modifier.padding(16.dp)) {
       Text(
           text = "Hello!",
           modifier = Modifier.padding(bottom = 8.dp),
           style = MaterialTheme.typography.h5
       )
       OutlinedTextField(
           value = "",
           onValueChange = { },
           label = { Text("Name") }
       )
   }
}      
Jetpack Compose 管理状态(一)

如果运行此代码,将不会看到任何反应。OutlinedTextField无法输入内容,这是因为,OutlinedTextField 不会自行更新,但会在其 value 参数更改时更新,这是因 Compose 中组合和重组的工作原理造成的.这里的更新即是OutlinedTextField可组合函数进行重组。

重要的词汇:

初始组合:通过首次运行可组合项创建组合。

组合:Jetpack Compose 在执行可组合项时构建的界面描述。

重组:在数据(状态)发生变化时重新运行可组合项以更新组合。

可组合项中的状态
Jetpack Compose 管理状态(一)

1.可组合函数可以使用 remember 可组合项记住单个对象,系统会在初始组合期间将由 remember 计算的值存储在组合中,并在重组期间返回存储的值。remember 既可用于存储可变对象,又可用于存储不可变对象。

2.mutableStateOf 会创建可观察的 MutableState,MutableState是与 Compose 运行时集成的可观察类型。

可组合项中声明 MutableState 对象的方法有三种:

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

tips:

虽然 remember 可帮助您在重组后保持状态,但不会帮助您在​​配置更改​​后保持状态,

为此,您必须使用 rememberSaveable。rememberSaveable 会自动保存可保存在 Bundle 中的任何值。

对于其他值,您可以将其传入自定义 Saver 对象。

remember 可组合项与 MutableState 可组合项关系

remember可组合项在可组合函数中保持状态。MutableState是实现了State接口的可被观察状态。写法上

remember { mutableStateOf(default) }      
其他受支持的状态类型

Jetpack Compose 支持其他可观察类型,在 Jetpack Compose 中读取其他可观察类型之前,您必须将其转换为State,以便 Jetpack Compose 可以在状态发生变化时自动重组界面。

Compose 附带一些可以根据 Android 应用中使用的常见可观察类型创建 State 的函数:

LiveData

Flow

RxJava2

要点:Compose 将通过读取 State接口 自动重组界面。

如果您在 Compose 中使用 LiveData 等其他可观察类型,应该先将其转换为 State,然后再使用诸如 LiveData.observeAsState() 之类的可组合扩展函数在可组合项中读取它。

注意:在 Compose 中将可变对象(如 ArrayList 或 mutableListOf())用作状态会导致用户在您的应用中看到不正确或陈旧的数据。是否是可观察对象取决于是否实现了State 接口,不推荐使用不可观察的对象

有状态与无状态

使用 remember 存储对象的可组合项会创建内部状态,使该可组合项有状态。HelloContent 就是一个有状态可组合项的示例,因为它会在内部保持和修改自己的 name 状态。在调用方不需要控制状态,并且不必自行管理状态便可使用状态的情况下,“有状态”会非常有用。但是,具有内部状态的可组合项往往不易重复使用,也更难测试。

无状态可组合项是指不保持任何状态的可组合项。实现无状态的一种简单方法是使用[状态提升]。

在开发可重复使用的可组合项时,您通常想要同时提供同一可组合项的有状态和无状态版本。有状态版本对于不关心状态的调用方来说很方便,而无状态版本对于需要控制或提升状态的调用方来说是必要的。

@Composable
fun HelloContent() {
   Column(modifier = Modifier.padding(16.dp)) {
       var name by remember { mutableStateOf("") }
       if (name.isNotEmpty()) {
           Text(
               text = "Hello, $name!",
               modifier = Modifier.padding(bottom = 8.dp),
               style = MaterialTheme.typography.h5
           )
       }
       OutlinedTextField(
           value = name,
           onValueChange = { name = it },
           label = { Text("Name") }
       )
   }
}      

系统提供rememberxxx 函数