我目前正在学习新的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
)
}
}
}
1条答案
按热度按时间46qrfjad1#
您正在执行如下更新:
这段代码获取
uiState
的当前值,并在其上调用build函数。Build函数创建AuthenticationState
的新示例,但您不对该新示例执行任何操作,它将被丢弃。您必须将此新示例设置为StateFlow的新值,如下所示: