谈谈Android Jetpack Compose中的状态提升
在本文中,我们将了解Jetpack Compose中的状态提升(State Hoisting
)。在深入研究这个主题之前,让我们先了解一下Jetpack Compose中的有状态(Stateful
)和无状态(Stateless
)组合。
有状态 vs 无状态(Stateful Vs Stateless)
使用remember
保存对象的组合会创建内部状态,使其成为有状态(Stateful)组合。
无状态组合是指不保存任何状态的组合。通过使用状态提升(State Hoisting)可以轻松实现无状态。
https://developer.android.com/jetpack/compose/state#state-hoisting
状态提升指的是,每当你创建任何子组合函数并且它被多次重用时,将它们变为无状态(Stateless
)。在子组合函数中不应该包含任何remember{mutableState()}
,而在父组合中调用此子组合函数时,将其设为有状态(Stateful
)。这样做可以方便地复用子组合函数。
父组合函数 - 有状态(
Stateful
)
子组合函数 - 无状态(Stateless
)
无状态提升
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun WithoutStateHoisting() {
var text by remember { mutableStateOf("") }
TextField(value = text, onValueChange = { text = it })
}
如上例所示,我们创建了一个组合函数,其中包含一个TextField并且在其中保存了一个状态。
这个例子没有问题,但是假设我们想要重用这个WithoutStateHoisting()
组合函数,那么我们很难做到这一点。
如果我想创建一个带有用户名和电子邮件字段的登录页面,我们可以在父组合中调用此组合函数两次,但问题是如何管理状态,因为我们在子组合函数中定义了状态,那么我怎么能够管理或识别出两个状态(邮箱和用户名)呢?
为了解决这个问题,我们需要依赖状态提升。
使用状态提升
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun WithStateHoistingExample(
title: String,
value: String,
onValueChange: (String) -> Unit
) {
TextField(value = value, onValueChange = onValueChange, placeholder = { Text(text = title) })
}
现在你可以看到,在上面的代码中,我们从这里移除了状态,而是使用了onValueChange: (String) -> Unit
来将值更新/发送到父组合函数。
value
:无论数据来自父组合还是子组合,都会在TextField中更新。
而且好消息是,这个组合函数是可重用的。
@Composable
fun StateHoisting(
modifier: Modifier
) {
var username by remember { mutableStateOf("") }
var email by remember { mutableStateOf("") }
Column(
modifier = modifier
.padding(20.dp)
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
WithStateHoistingExample(
title = stringResource(R.string.username),
value = username,
onValueChange = { username = it })
Spacer(modifier = Modifier.height(20.dp))
WithStateHoistingExample(
title = stringResource(R.string.email),
value = email,
onValueChange = { email = it })
}
}
你可以看到我们在上面创建了两个状态,用户名和电子邮件,并将这些状态传递到子组合函数WithStateHoistingExample()
中。
结论
状态提升是在Jetpack Compose中推荐使用的一种方式。请注意,如果你的子组合函数被多次重用,请不要使其有状态函数( stateful),始终使用状态提升以便可以重用并使它们感觉独立。
Github
https://github.com/nameisjayant/compose-blogs-repository/tree/main/app/src/main/java/com/nameisjayant/articlesrepository/ui/stateHositing?source=post_page