LiveData observer never getting removed between shared ViewModel

137 Views Asked by At

I'm becoming crazy.

I have a SharedViewModel shared between FragmentA and FragmentB, which contains a LiveData:

class SharedViewModel : ViewModel() {

    private val _searchParameters = MutableLiveData(SearchParameters())
    val searchParameters: LiveData<SearchParameters> = _searchParameters
}

and I observe this liveData in the onViewCreated() of my FragmentA (only, not in FragmentB):

viewModel.searchParameters.observe(viewLifecycleOwner) { searchAndFilter ->
   Log.d("FragmentA", "observed searchParameters in FragmentA")
   mSearchAdapter.updateSearchParameters(searchAndFilter)
}

My problem is that the observer never gets removed when FragmentA is destroyed:

If I navigate to FragmentB (using Navigation Component), then from FragmentB I do findNavController().popBackStack(), I would expect FragmentA to have removed my observer in onDestroyView() (which I have confirmed is called correctly when navigating to FragmentB). But this isn't happening. So when I navigate back to FragmentA, the LiveData is being observed another time, and now I have multiple observations of this LiveData. If I navigate back and forth 10 times, my observer has now been registered 10 times and is being called 10 times foe every event.

I have also tried removing the observer manually by keeping a reference to it and doing

override fun onDestroyView() {
     super.onDestroyView()

     Log.d("FragmentA", "onDestroyView")
     viewModel.searchParameters.removeObserver(searchParametersObserver)
}

But the same problem occurs.

So my question is what is going on, and how can I fix this problem?

2

There are 2 best solutions below

0
william xyz On

I created a sample test project at Github link that goes from fragmentA to FragmentB. It seems to work correctly, when on FragmentB, FragmentA stops receiving events and when back to FragmentA, FragmentB stops receiving events. And FragmentA is always reused while fragmentB is recreated (see hashCodes)

enter image description here

I think your problem could be caused by something else such as: wrong sharedViewModel config, incorrect navigation configuration on navigation.xml or incorrect navigation from A to B. I suggest checking the sample link and see if what you're doing matches it.

0
Algimantas On

It could be that only fragment's view is destroyed, but not the fragment itself.

Check if setting up observers in onCreate instead of onCreateView would resolve your issue.