我可以在 Compose 中使用 mutableStateOf() 而不是 produceState 吗?
Can I use mutableStateOf() instead of produceState in Compose?
代码A来自官方样本project。
我认为 produceState
没有必要,所以我想我可以用代码 B 替换代码 A,对吗?
顺便说一句,代码B可以运行。
代码A
@Composable
fun DetailsScreen(
onErrorLoading: () -> Unit,
modifier: Modifier = Modifier,
viewModel: DetailsViewModel = viewModel()
) {
val uiState by produceState(initialValue = DetailsUiState(isLoading = true)) {
val cityDetailsResult = viewModel.cityDetails
value = if (cityDetailsResult is Result.Success<ExploreModel>) {
DetailsUiState(cityDetailsResult.data)
} else {
DetailsUiState(throwError = true)
}
}
when {
uiState.cityDetails != null -> {
DetailsContent(uiState.cityDetails!!, modifier.fillMaxSize())
}
uiState.isLoading -> {
...
}
else -> { onErrorLoading() }
}
}
代码B
@Composable
fun DetailsScreen(
onErrorLoading: () -> Unit,
modifier: Modifier = Modifier,
viewModel: DetailsViewModel = viewModel()
) {
var uiState by remember {mutableStateOf(DetailsUiState(isLoading = true))}
val cityDetailsResult = viewModel.cityDetails
uiState = if (cityDetailsResult is Result.Success<ExploreModel>) {
DetailsUiState(cityDetailsResult.data)
} else {
DetailsUiState(throwError = true)
}
when {
uiState.cityDetails != null -> {
DetailsContent(uiState.cityDetails!!, modifier.fillMaxSize())
}
uiState.isLoading -> {
...
}
else -> { onErrorLoading() }
}
}
让我们来看看 productState
的幕后花絮:
@Composable
fun <T> produceState(
initialValue: T,
@BuilderInference producer: suspend ProduceStateScope<T>.() -> Unit
): State<T> {
val result = remember { mutableStateOf(initialValue) }
LaunchedEffect(Unit) {
ProduceStateScopeImpl(result, coroutineContext).producer()
}
return result
}
productState
在其参数中没有键,使用 LaunchedEffect
和 Unit
键创建一个与调用站点的生命周期相匹配的效果。
表示如果DetailsScreen
重组,提供uiState
的代码将不会重新开始
但是在代码 B 中,你只是记住 DetailsUiState
跨重组,下面的行将在每次重组时执行。
val cityDetailsResult = viewModel.cityDetails
uiState = if (cityDetailsResult is Result.Success<ExploreModel>) {
DetailsUiState(cityDetailsResult.data)
} else {
DetailsUiState(throwError = true)
}
代码A来自官方样本project。
我认为 produceState
没有必要,所以我想我可以用代码 B 替换代码 A,对吗?
顺便说一句,代码B可以运行。
代码A
@Composable
fun DetailsScreen(
onErrorLoading: () -> Unit,
modifier: Modifier = Modifier,
viewModel: DetailsViewModel = viewModel()
) {
val uiState by produceState(initialValue = DetailsUiState(isLoading = true)) {
val cityDetailsResult = viewModel.cityDetails
value = if (cityDetailsResult is Result.Success<ExploreModel>) {
DetailsUiState(cityDetailsResult.data)
} else {
DetailsUiState(throwError = true)
}
}
when {
uiState.cityDetails != null -> {
DetailsContent(uiState.cityDetails!!, modifier.fillMaxSize())
}
uiState.isLoading -> {
...
}
else -> { onErrorLoading() }
}
}
代码B
@Composable
fun DetailsScreen(
onErrorLoading: () -> Unit,
modifier: Modifier = Modifier,
viewModel: DetailsViewModel = viewModel()
) {
var uiState by remember {mutableStateOf(DetailsUiState(isLoading = true))}
val cityDetailsResult = viewModel.cityDetails
uiState = if (cityDetailsResult is Result.Success<ExploreModel>) {
DetailsUiState(cityDetailsResult.data)
} else {
DetailsUiState(throwError = true)
}
when {
uiState.cityDetails != null -> {
DetailsContent(uiState.cityDetails!!, modifier.fillMaxSize())
}
uiState.isLoading -> {
...
}
else -> { onErrorLoading() }
}
}
让我们来看看 productState
的幕后花絮:
@Composable
fun <T> produceState(
initialValue: T,
@BuilderInference producer: suspend ProduceStateScope<T>.() -> Unit
): State<T> {
val result = remember { mutableStateOf(initialValue) }
LaunchedEffect(Unit) {
ProduceStateScopeImpl(result, coroutineContext).producer()
}
return result
}
productState
在其参数中没有键,使用 LaunchedEffect
和 Unit
键创建一个与调用站点的生命周期相匹配的效果。
表示如果DetailsScreen
重组,提供uiState
的代码将不会重新开始
但是在代码 B 中,你只是记住 DetailsUiState
跨重组,下面的行将在每次重组时执行。
val cityDetailsResult = viewModel.cityDetails
uiState = if (cityDetailsResult is Result.Success<ExploreModel>) {
DetailsUiState(cityDetailsResult.data)
} else {
DetailsUiState(throwError = true)
}