Manually clearing an Android ViewModel?
Quick solution without having to use Navigation Component
library:
getActivity().getViewModelStore().clear();
This will solve this problem without incorporating the Navigation Component
library. It’s also a simple one line of code. It will clear out those ViewModels
that are shared between Fragments
via the Activity
If you check the code here you'll find out, that you can get the ViewModelStore
from a ViewModelStoreOwner
and Fragment
, FragmentActivity
for example implements, that interface.
Soo from there you could just call viewModelStore.clear()
, which as the documentation says:
/**
* Clears internal storage and notifies ViewModels that they are no longer used.
*/
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
N.B.: This will clear all the available ViewModels for the specific LifeCycleOwner, this does not allow you to clear one specific ViewModel.
As OP and Archie said, Google has given us the ability to scope ViewModel to navigation graphs. I will add how to do it here if you are using the navigation component already.
You can select all the fragments that needs to be grouped together inside the nav graph and right-click->move to nested graph->new graph
now this will move the selected fragments to a nested graph inside the main nav graph like this:
<navigation app:startDestination="@id/homeFragment" ...>
<fragment android:id="@+id/homeFragment" .../>
<fragment android:id="@+id/productListFragment" .../>
<fragment android:id="@+id/productFragment" .../>
<fragment android:id="@+id/bargainFragment" .../>
<navigation
android:id="@+id/checkout_graph"
app:startDestination="@id/cartFragment">
<fragment android:id="@+id/orderSummaryFragment".../>
<fragment android:id="@+id/addressFragment" .../>
<fragment android:id="@+id/paymentFragment" .../>
<fragment android:id="@+id/cartFragment" .../>
</navigation>
</navigation>
Now, inside the fragments when you initialise the viewmodel do this
val viewModel: CheckoutViewModel by navGraphViewModels(R.id.checkout_graph)
if you need to pass the viewmodel factory(may be for injecting the viewmodel) you can do it like this:
val viewModel: CheckoutViewModel by navGraphViewModels(R.id.checkout_graph) { viewModelFactory }
Make sure its R.id.checkout_graph
and not R.navigation.checkout_graph
For some reason creating the nav graph and using include
to nest it inside the main nav graph was not working for me. Probably is a bug.
Source: https://medium.com/androiddevelopers/viewmodels-with-saved-state-jetpack-navigation-data-binding-and-coroutines-df476b78144e
Thanks, OP and @Archie for pointing me in the right direction.