Reset/clear viewmodel or livedata

Viewed 2740

I am following the one-single-activity app pattern advised by Google, so if I want to share data between Fragments I have to share a ViewModel whose owner must be the parent Activity. So, the problem becomes because I want to share data between only two Fragments, independently from the others.

Imagine I have MainFragment, CreateItemFragment and ScanDetailFragment. So, from first one I navigate to CreateItemFragment in which whenever I press a button I navigate to ScanDetailFragment in order to scan a barcode and, in consequence, through a LiveData object inside the ViewModel I can get the scanned value back into the CreateItemFragment once ScandDetailFragment finishes. The problem becomes when I decide to cancel the creation of the item: I go back to the `MainFragment' and because the ViewModel's owner was the Activity's lifecycle, once I go again into CreateItemFragment, the previously scanned value is still there.

Any idea to reset that ViewModel?

5 Answers

but, aren't Viewmodels also aimed to share data between different views?

No. Each viewmodel should be responsible for one view. The "shared viewmodel" pattern is for cases when you have one large view (i.e., activity) that has multiple subviews (i.e., fragments) that need to share data / state, like the master / detail example in the documentation. It's a convenience for these cases when you need real-time updates amongst the subviews.

In your case, you're navigating between fragments and as such should be passing data through the transitions. This means passing arguments along when starting new fragments and registering for results when they complete their task.

Then each of your fragments is isolated, self-contained, more easily testable and you won't end up with a God-ViewModel that does All The Things™ and turns into a giant mess as you try to jump through hoops accounting for every state it could possibly be in.

You can clear LiveData value every time when you go into CreateItemFragment from MainFragment.

Or you can just clear it from the CreateItemFragment in onBackPressed() method.

When you cancel the creation of item,set livedata value to null.then within observer code if(updatedvalue!=null) write your code using updated live data value.in this way you can avoid last updated value.

At the moment (on 2022), the method viewmodel.getViewModelStore.clear(); or onCleared(); is deprecated.

So, if you want to clear data holded by ViewModel or clear value of LiveData, you just need use 1 line code like this:

mainViewModel.getLiveData().getValue().clear();
  • getLiveData() is my method inside MainViewModel class to return liveData variable
  • getValue() is defaut method provided by LiveData (MutableLiveData: setValue(), postValue())

If you need to clear data when user press on Back button in Fragment, you can do like the code below & put it inside the onViewCreated method - the method of LifecycleFragment.

private void handleOnBackPressed() {
        requireActivity().getOnBackPressedDispatcher().addCallback(new OnBackPressedCallback(true) {
            @Override
            public void handleOnBackPressed() {
                Objects.requireNonNull(mainViewModel.getLiveData().getValue()).clear();
                requireActivity().finish();
            }
        });
    }

My project on Git if you want to refer code (it still updated): https://github.com/Nghien-Nghien/PokeAPI-Java/blob/master/app/src/main/java/com/example/pokemonapi/fragment/MainFragment.java

Related