Issue
I can't figure out how states work in jetpack compose, as I read, whenever the value changes in a State or mutablestate changes it's supposed to force recomposition and change the view, but that doesn't happen in my case
Here I am posting data to server and I receive the response successfully in my log
@HiltViewModel
class LoginViewModel @Inject constructor(
private val loginUseCase: CheckPhoneUseCase
) : ViewModel() {
private val _state = mutableStateOf(ResponseState())
val state : State<ResponseState> = _state
fun checkPhone(phone: String) : Boolean{
val body = PhoneBodyModel(phone.trim())
loginUseCase.checkPhone(body).onEach { response ->
when (response) {
is Resource.Success -> {
_state.value = ResponseState(isSuccess = response.data?.status ?: false)
Log.v("LoginViewModel", "checkPhone: ${_state.value.isSuccess}")
}
is Resource.Error -> {
_state.value = ResponseState(isError = response.message ?: "UnExpected Error")
Log.v("LoginViewModel", "checkPhone: ${response.message}")
}
is Resource.Loading -> {
_state.value = ResponseState(isLoading = true)
}
}
}.launchIn(viewModelScope)
return _state.value.isSuccess
}
and in my Compose Screen
if (!phoneOrEmail.isEmpty()){
viewModel.checkPhone(phoneOrEmail)
Log.v("viewModel.state", viewModel.state.value.isSuccess.toString())
if (viewModel.state.value.isSuccess){
Log.v("viewModel.state", viewModel.state.value.isSuccess.toString())
navController.navigate(route = Screen.OTPScreen.withArgs(phoneOrEmail))
}
// Toast.makeText(context, "Phone number is not registered", Toast.LENGTH_LONG).show()
}
UADProgressBare(isDisplayed = viewModel.state.value.isLoading, modifier = Modifier.padding(24.dp))
and through logging, I can see that the data is received, yet in my Compose Screen the data doesn't change at all from its initial value and doesn't force recomposition, as I read and watched online, that State and MutablkeState suppose to force recomposition and receive the new value whenever it changes just like LiveData, yet it doesn't work as LiveData for me, I don't know what is my mistake here so I can force recomposition whenever the value changes.
Solution
Maybe you should use this way:
@Composable
fun ComposeScreen() {
//initiate your check phone or email
...
LaunchedEffect(Unit) {
snapshotFlow { viewModel.state.value }
.collect {
if (it.isSuccess) ... else ...
}
}
}
or
@Composable
fun ComposeScreen() {
//initiate your check phone or email
...
LaunchedEffect(viewModel.state.value) {
if (viewModel.state.value.isSuccess){ ... }
}
Answered By - ngalashev
Answer Checked By - Candace Johnson (JavaFixing Volunteer)