我用Compose编写了一个表单屏幕,用户可以在其中填写一些TextField
并提交它。如果他们在填写字段之前按下提交按钮,空TextField
s的支持文本将更改为“Required”。
Required text on empty fields
为此,我创建了一个包含showRequired
字段的ViewState
:
data class ViewState(
showRequired: Boolean = false,
// other fields
)
在我的视图模型中,我创建了一个MutableStateFlow
,并将ViewState
作为其默认值:
private val _viewState: MutableStateFlow<ViewState> = MutableStateFlow(ViewState())
val viewState: StateFlow<viewState> = _viewState.asStateFlow()
为了让组合显示所需的消息,我像这样更新视图状态:
fun onSubmitClicked(form: Form) {
if (areRequiredFieldsMissing(form)) {
_viewState.update { it.copy(showRequired = true) }
}
}
在我的composable中,我使用collectAsStateWithLifecycle()
收集该流,然后在显示消息之前检查showRequired = true
是否为:
val viewState = viewModel.viewState.collectAsStateWithLifecycle()
if (viewState.value.showRequired) {
// set supportingText = Required
}
当我单击提交按钮时,消息按预期显示。但是,如果我离开这个屏幕,然后再回到它,所需的消息会默认显示,而不是隐藏。我想我可以通过在按下后退按钮设置showRequired = false
时更新视图状态来解决这个问题:
// in my view model
fun onBackPressed() {
_viewState.update { it.copy(showRequired = false) }
}
然而,这并不能解决任何问题。当我返回表单屏幕时,默认情况下仍显示所需的消息。当我调试组合时,为showRequired
收集的值仍然为true。为什么将其更新为false不能正常工作,而在单击提交按钮时将其更新为true却可以?我想我误解了StateFlow
的工作原理,但我不确定该尝试什么。
编辑:我通过在退出屏幕时重置我的ViewState
来解决这个问题,这样showRequired
就被重置为false,而不仅仅是更新它。
_viewState.value = ViewState()
2条答案
按热度按时间wz1wpwve1#
showRequired
应该是一个单独的SharedFlow,不应该像StateFlow一样保持状态,当提交时有一个空字段时显示消息是一个事件而不是一个状态,你应该只显示一次。StateFlow保持其值,当您从不同的屏幕返回时,会发生重新组合此代码块再次执行,并且由于
showRequired
in state is set true,因此将显示消息。您应该从viewState中删除
showRequired
在Composable中
wlsrxk512#
这是我对用例的理解。
如果不完全相同,请添加注解。
您有一个包含多个
TextFields
和一个SubmitButton
的屏幕。单击提交按钮后,应用程序将导航到另一个屏幕。状态在屏幕之间的共享ViewModel中维护。错误消息仅在用户单击按钮但验证失败后显示。
我的第一个建议是使用屏幕级别的
ViewModel
,而不是共享的ViewModel
,它会在删除时自动清除状态。但是,可能存在不可能的情况。这样的话,你可以试试这个
我们使用Kotlin的
combine
来监听TextField
输入状态和CTA按钮点击状态。离开屏幕导航时,应重置
ctaClicked
。如果这对您的用例不起作用,请提供更多细节。