Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Manually clearing an Android ViewModel?

Edit: This question is a bit out of date now that Google has given us the ability to scope ViewModel to navigation graphs. The better approach (rather than trying to clear activity-scoped models) would be to create specific navigation graphs for the right amount of screens, and scope to those.


With reference to the android.arch.lifecycle.ViewModel class.

ViewModel is scoped to the lifecycle of the UI component it relates to, so in a Fragment-based app, that will be the fragment lifecycle. This is a good thing.


In some cases one wants to share a ViewModel instance between multiple fragments. Specifically I am interested in the case where many screens relate to the same underlying data.

(The docs suggest similar approach when multiple related fragments are displayed on the same screen but this can be worked around by using a single host fragment as per answer below.)

This is discussed in the official ViewModel documentation:

ViewModels can also be used as a communication layer between different Fragments of an Activity. Each Fragment can acquire the ViewModel using the same key via their Activity. This allows communication between Fragments in a de-coupled fashion such that they never need to talk to the other Fragment directly.

In other words, to share information between fragments that represent different screens, the ViewModel should be scoped to the Activity lifecycle (and according to Android docs this can also be used in other shared instances).


Now in the new Jetpack Navigation pattern, it is recommended to use a "One Activity / Many Fragments" architecture. This means that the activity lives for the whole time the app is being used.

i.e. any shared ViewModel instances that are scoped to Activity lifecycle will never be cleared - the memory remains in constant use.

With a view to preserving memory and using as little as required at any point in time, it would be nice to be able to clear shared ViewModel instances when no longer required.


How can one manually clear a ViewModel from it's ViewModelStore or holder fragment?

like image 557
Richard Le Mesurier Avatar asked Dec 06 '18 14:12

Richard Le Mesurier


People also ask

Is ViewModel destroyed when activity destroy?

The ViewModel exists from when you first request a ViewModel until the activity is finished and destroyed.

How is ViewModel retained?

ViewModel objects are automatically retained during configuration changes so that data they hold is immediately available to the next activity or fragment instance. FYI: You can use ViewModel to preserve UI state only during a configuration change, nothing else as explained perfectly in this official doc.

Does ViewModel store data?

The ViewModel stores the app related data that isn't destroyed when activity or fragment is destroyed and recreated by the Android framework.


2 Answers

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

like image 109
Sakiboy Avatar answered Oct 23 '22 16:10

Sakiboy


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.

like image 23
Róbert Nagy Avatar answered Oct 23 '22 17:10

Róbert Nagy