A.D*_*ibo 0 android kotlin android-jetpack-compose kotlin-stateflow
我目前正在学习新的 Android 堆栈(MVVM、compose、kotlin Flow/StateFlow),并且在调试值更新的 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)
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
用户界面组件:
@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
)
}
Run Code Online (Sandbox Code Playgroud)
状态数据类:
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
)
}
}
}
Run Code Online (Sandbox Code Playgroud)
您正在执行这样的更新:
_uiState.value.build {
isLoading = true
}
Run Code Online (Sandbox Code Playgroud)
此代码获取当前值uiState并在其上调用构建函数。Build 函数创建 的新实例,AuthenticationState但您不对该新实例执行任何操作,并且它会被丢弃。您必须将此新实例设置为 StateFlow 的新值,如下所示:
_uiState.value = _uiState.value.build {}
// or this:
_uiState.update { current -> current.build {} }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1920 次 |
| 最近记录: |