How to cancel collect coroutine StateFlow?

4.9k Views Asked by At

I have collect flow from shared viewmodel in fragment :

private val viewModel: MyViewModel by sharedViewModel()

private fun observeViewModelStateFlowData() {
job = lifecycleScope.launch {
            viewModel.stateFlowData.collect {
                when (it) {
                    is ViewStates.Success -> handleSuccess(it.data)
                }
            }
        }
    }

in ViewModel :

private val _stateFlowData = MutableStateFlow<ViewStates<Model>>(ViewStates.Idle)
val stateFlowData: StateFlow<ViewStates<Model>> get() = _stateFlowData

but when I go to next fragment and back to this fragment again, flow collect again. I cancel the job in onStop() lifecycle method of fragment :

override fun onStop() {
    job?.cancel()
    super.onStop()
}

but not cancel and collect again!!!

This happens even when I leave the activity (when the viewmodel is cleared) and come back to activity again!!!

How can I do this so that I can prevent the collecting of flow ?

1

There are 1 best solutions below

0
On

Well you have to know something about coroutine. If we just call cancel, it doesn’t mean that the coroutine work will just stop. If you’re performing some relatively heavy computation, like reading from multiple files, there’s nothing that automatically stops your code from running.

You need to make sure that all the coroutine work you’re implementing is cooperative with cancellation, therefore you need to check for cancellation periodically or before beginning any long running work. Try to add check before handling a result.

job = lifecycleScope.launch {
            viewModel.stateFlowData.collect {
                ensureActive()
                when (it) {
                    is ViewStates.Success -> handleSuccess(it.data)
                }
            }
        }
    }

For more info take a look on this article https://medium.com/androiddevelopers/cancellation-in-coroutines-aa6b90163629