Home > Software engineering >  Kotlin StateFlow multiple subscriptions after returning from another Fragment
Kotlin StateFlow multiple subscriptions after returning from another Fragment

Time:04-16

I'm trying to implement StateFlow in my app with MVVM architecture between ViewModel and Fragment.

In ViewModel:

...

private val _eventDataState = MutableStateFlow<EventDataState>(EventDataState.Loading)
val eventDataState: StateFlow<EventDataState> = _eventDataState

...

In Fragment:

...

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        ...

        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.eventDataState.collect { eventDataState ->
                    when (eventDataState) {
                        is EventDataState.Loading -> {}
                        is EventDataState.Success -> onEventDataUpdated(data = eventDataState)
                        is EventDataState.Deleted -> onEventDataDeleted()
                    }
                }
            }
        }
        viewModel.getEventData()
    }

...

All seems to work well:

2022-04-15 17:57:20.352 5251-5251/ ... E/EVENT: Data state: Success(...)

But when I switch to another Fragment through Activity's SupportFragmentManager and then hit Back button I get multiple responses from StateFlow:

2022-04-15 17:57:30.358 5251-5251/ ... E/EVENT: Data state: Success(...)
2022-04-15 17:57:30.362 5251-5251/ ... E/EVENT: Data state: Success(...)

So the more times I switch to another Fragment and back - the more copies of response I get from StateFlow (this is not initial StateFlow value).

My guess is that when another Fragment are called the first one destroys its view but subscription to Flow is still exists, and when returning back from another Fragment the first one calls its onViewCreated and so creating another copy of subscription to this Flow. Nevertheless I was unable to find any solution to my case on stackoverflow or any other resources.

What have I missed?

CodePudding user response:

You should use viewLifecycleOwner.lifecycleScope.launch in fragments. viewLifecycleOwner.lifecycleScope and all its jobs will be cancelled when the view is destroyed.

  • Related