12

I have a login form. I use StateFlow to send LoginResult (after call API) from ViewModel to Activity. In the Activity, I will show an error dialog if login failed.
It works well for the first time but from the second time I login failed, the error dialog won't show again. I tested both .value and .emit on StateFlow

private val _loginResult = MutableStateFlow(LoginResult())
val loginResult: StateFlow<LoginResult> = _loginResult

fun login(email: String, password: String) {
    viewModelScope.launch {
        when (val result = loginRepository.login(email, password)) {
            is Result.Fail-> {
                _loginResult.value = LoginResult(error = "Login failed")
                // _loginResult.emit(LoginResult(error = "Login failed")) same issue
            }
            ...
       }
   }
}
beigirad
  • 4,986
  • 2
  • 29
  • 52
Linh
  • 57,942
  • 23
  • 262
  • 279
  • 4
    StateFlow does not emit duplicate value. you can user SharedFlow to solve your problem. – Omid Faraji Jan 06 '21 at 08:44
  • @OmidFaraji yes, I have solved it in my answer. It takes me some time to solve this problem so I post it here – Linh Jan 06 '21 at 08:47

2 Answers2

4

For this case, I use SharedFlow so my Activity still able to collect the new value even it same the last value

private val _loginResult = MutableSharedFlow<LoginResult>()
val loginResult: SharedFlow<LoginResult> = _loginResult

...
_loginResult.emit(LoginResult(error = "Login failed"))

Another possible solution but it's not good is change my current data class LoginResult(...) to class LoginResult. Then every new instance of LoginResult will different

Linh
  • 57,942
  • 23
  • 262
  • 279
  • Why is SharedFlow better than StateFlow for this? – IgorGanapolsky Mar 08 '23 at 15:58
  • @IgorGanapolsky so normally, I use StateFlow to store UI state, and SharedFlow to emit event. we shouldn't use StateFlow for event, because if you rotate the screen, the event can trigger again. – Linh Mar 09 '23 at 02:00
0

That's by default. What you could do is to emit one value when the login is in progress, before emitting the result. That way you would have a sequence like:

in_progress -> error -> in_progress -> error

Apps usually display a spinner or something when the in_progress or loading or whatever is emitted.

Serandel
  • 417
  • 5
  • 20