Home > Software design >  Observing variable in viewmodel is not working
Observing variable in viewmodel is not working

Time:02-23

I have this code in which I am trying to observe a variable from my viewmodel. However, whenever I observe the variable, it always returns false, which is the default value, even though it should be returning true. I don't understand why it's not working, any idea and advice would be great.

This is the viewmodel part:

val isSuccessful = MutableLiveData(false)

fun acceptAgreement() = currentAgreement.value?.let {
       viewModelScope.launch {
           runCatching { agreementsRepository.acceptAgreement(it.id) }
               .onSuccess { isSuccessful.postValue(true) }
               .onFailure { isSuccessful.postValue(false) }
       }
   }

The observation in the fragment, where it always returns the showError():

binding.btnAccept.setOnClickListener { onAccept().also { continue()} }
private fun onAccept() = viewModel.acceptAgreement()

private fun continue() {
      viewModel.isSuccessful.observe(viewLifecycleOwner, {
           if (it) { start() } else { showError() }
       })
   }

Repository:

suspend fun acceptAgreement(id: String) = changeAgreement(id, status.ACCEPTED)

private suspend fun changeAgreement(id: String, status: status) {
       try { agreementsService.changeAgreement(id, status.serialize()) }
       catch (e: Throwable) { logger.error(this::class.java.name, "Failed to change status ${id}", e) }
   }

CodePudding user response:

 isSuccessful.postValue(
            runCatching { agreementsRepository() }.isSuccess
        )

CodePudding user response:

Instead of using isSuccessful.postValue() use isSuccessful.value = true. I have found that assignment, not the postValue method, updates registered observers for LiveData.

CodePudding user response:

Is there a reason you are running continue() after your run onAccept?

I believe what is happening is you haven't set the observer before you are observing.

So your flow goes:

onAccept -> triggers the update of the livedata. Continue -> Sets the observer of the livedata.

I would suggest that you move the method call "continue()" into your onCreateView method of the fragment. It won't be triggered until it changes state in the viewmodel anyway.

Also you need to check you have set the viewLifecycleOwner of the fragment.

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    val binding =  FragmentYourFragmentNameBinding.inflate(inflater, container, false).apply {
        lifecycleOwner = viewLifecycleOwner
    }

    continue()

    return binding.root
}
  • Related