android 状态流已更新但未收集

rqqzpn5f  于 2022-12-16  发布在  Android
关注(0)|答案(1)|浏览(143)

我目前正在学习新的Android堆栈(MVVM、compose、KotlinFlow/StateFlow),我在调试值更新的StateFlow时遇到了麻烦,但我没有从可组合堆栈收集的迹象。
这是一个一般性的问题,但我没有找到任何解决我的问题,我自己的搜索。
有人知道什么会扰乱状态流吗?我让我的代码如下:
视图模型:

@HiltViewModel
class AuthViewModel @Inject constructor(
    private val navigationManager: NavigationManager,
    private val interactor: AuthInteractor
): BaseViewModel() {

    companion object {
        val TAG: String = AuthViewModel::class.java.simpleName
    }

    private val _uiState = MutableStateFlow(AuthenticationState())
    val uiState: StateFlow<AuthenticationState> = _uiState

    fun handleEvent(event: AuthenticationEvent) {
        Log.v(TAG, "new event: $event")
        when (event) {
            is AuthenticationEvent.GoToRegistering -> navigateToRegistering()
            is AuthenticationEvent.Register -> registerAccount(event)
            is AuthenticationEvent.SnackbarMessage -> showSnackBar(event.message, event.type)
        }
    }

    private fun navigateToRegistering() {
        navigationManager.navigate(NavigationDirections.Authentication.registering)
    }

    private fun registerAccount(event: AuthenticationEvent.Register) {
        Log.v(TAG, "register account")
        _uiState.value.build {
            isLoading = true
        }

        viewModelScope.launch {
            Log.v(TAG, "launching request")
            val exceptionMessage = interactor.registerUser(event.login, event.password)
            Log.v(TAG, "response received, launching state from viewmodel")

            _uiState.value.build {
                exceptionMessage?.let {
                    Log.v(TAG, "Exception is not null")
                    isFailure = true
                    snackbarMessage = interactor.selectRegisterError(it)
                }
            }
        }
    }

}

UI组件:

@Composable
fun Authentication(
    modifier: Modifier = Modifier,
    viewModel: AuthViewModel,
    type: AuthenticationType
) {
    val state by viewModel.uiState.collectAsState()
    Log.v("Authentication", "new state: $state, type = $type")

    BackHandler(enabled = true) {
        viewModel.handleEvent(AuthenticationEvent.Back)
    }

    state.snackbarMessage?.let { resourceId ->
        val message = stringResource(resourceId)
        Log.e("Authentication", "error: $message")
        viewModel.handleEvent(AuthenticationEvent.SnackbarMessage(message, SnackbarType.ERROR))
    }

    if (state.isAuthenticated) {
        // TODO: launch main screen
    }

    LaunchedEffect(key1 = state.isRegistered) {
        // TODO: launch login event
    }

    AuthenticationContent(
        modifier = modifier,
        type = type,
        viewModel = viewModel,
        state = state
    )
}

状态数据类:

data class AuthenticationState(
    val isLoading: Boolean = false,
    val isFailure: Boolean = false,
    val isRegistered: Boolean = false,
    val isAuthenticated: Boolean = false,
    @StringRes val snackbarMessage: Int? = null
)  {

    fun build(block: Builder.() -> Unit) = Builder(this).apply(block).build()

    class Builder(uiModel: AuthenticationState) {
        var isLoading = uiModel.isLoading
        var isFailure = uiModel.isFailure
        var isRegistered = uiModel.isRegistered
        var isAuthenticated = uiModel.isAuthenticated
        var snackbarMessage = uiModel.snackbarMessage

        fun build(): AuthenticationState {
            return AuthenticationState(
                isLoading,
                isFailure,
                isRegistered,
                isAuthenticated,
                snackbarMessage
            )
        }
    }
}
46qrfjad

46qrfjad1#

您正在执行如下更新:

_uiState.value.build {
    isLoading = true
}

这段代码获取uiState的当前值,并在其上调用build函数。Build函数创建AuthenticationState新示例,但您不对该新示例执行任何操作,它将被丢弃。您必须将此新示例设置为StateFlow的新值,如下所示:

_uiState.value = _uiState.value.build {}
// or this:
_uiState.update { current -> current.build {} }

相关问题