Flow 不更新 Composable

Flow doesn't update Composable

我遇到了以下问题:

这是注册屏幕,上面有几个输入字段。当用户输入内容时,该值将传递给 ViewModel,设置为屏幕状态并通过 StateFlow 传回屏幕。从可组合项中,我正在观察此 StateFlow。问题是 Composable 在向 Flow 发出新值后并未失效。

这是 ViewModel 代码:

class RegistrationViewModel : BaseViewModel() {

    private val screenData = CreateAccountRegistrationScreenData.init()

    private val _screenDataFlow = MutableStateFlow(screenData)
    internal val screenDataFlow = _screenDataFlow.asStateFlow()

    internal fun updateFirstName(name: String) {
        screenData.firstName = name
        updateScreenData()
    }

    private fun updateScreenData() {
        viewModelScope.launch {
            _screenDataFlow.emit(screenData.copy())
        }
        println()

    }

}

这是可组合代码:

@Composable
fun RegistrationScreen(navController: NavController, stepName: String) {
    val focusManager = LocalFocusManager.current

    val viewModel: RegistrationViewModel by rememberInstance()

    val screenData by viewModel.screenDataFlow.collectAsState()

    Scaffold {
        ConstraintLayout(
            modifier = Modifier
                .fillMaxSize()
                .pointerInput(Unit) {
                    detectTapGestures(onTap = {
                        focusManager.clearFocus()
                    })
                },
        ) {
            val (
                textTopLabel,
                textBottomLabel,
                tfFirstName,
                tfLastName,
                tfEmail,
                tfPassword,
                btnNext
            ) = createRefs()

            ...
            RegistrationOutlinedTextField(
                value = screenData.firstName ?: "",
                constraintAsModifier = {
                    constrainAs(tfFirstName) {
                        top.linkTo(textBottomLabel.bottom, margin = Padding30)
                        start.linkTo(parent.start)
                        end.linkTo(parent.end)
                    }
                },
                label = { Text("First Name", style = PoppinsNormalStyle14) },
                leadingIcon = {
                    Image(
                        painter = painterResource(id = R.drawable.ic_user_login),
                        contentDescription = null
                    )
                },
                onValueChange = { viewModel.updateFirstName(it) }
            )
    }
}

在此先感谢您的帮助

你的问题是你正在改变你的状态,所以流程中使用的 equals 总是 returns true。

改变这个

internal fun updateFirstName(name: String) {
    screenData.firstName = name
    updateScreenData()
}

private fun updateScreenData() {
    viewModelScope.launch {
        _screenDataFlow.emit(screenData.copy())
    }
    println()

}

internal fun updateFirstName(name: String) {
    viewModelScope.launch {
        _screenDataFlow.emit(screenData.copy(firstName = name))
    }
}

在您的情况下,您的 MutableStateFlow 持有可变值的 link,这就是为什么当您传递 hashcode(根据所有字段值计算)的值时相同的原因,流程不会更新值。

查看 Why is immutability important in functional programming?

data class 是一个很好用的工具,它将为您提供开箱即用的所有 copy,但您应该使用 var 发出并且只使用 val 为您的字段避免错误。

此外,使用 MutableStateFlow,您始终可以访问 value,因此您无需将其存储在单独的变量中:

class RegistrationViewModel : BaseViewModel() {

    private val _screenDataFlow = MutableStateFlow(CreateAccountRegistrationScreenData())
    internal val screenDataFlow = _screenDataFlow.asStateFlow()

    internal fun updateFirstName(name: String) {
        _screenDataFlow.update { screenData ->
            screenData.copy(firstName = name)
        }
    }
}