Manually clearing an Android ViewModel?

android-viewmodel oncleared
clear livedata android
android viewmodel singleton
android viewmodel oncleared not called
android viewmodel fragment example
android kotlin viewmodel
advantages of viewmodel android
reuse viewmodel android

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?

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.

Manually clearing an Android ViewModel?, ViewModelStore has a clear() method, but it clears all viewmodels in it. Is there some way to clear specific ViewModel? Another solution is to scope ViewModel  For example, when testing a ViewModel that depends on a repository, you can pass different implementations of Repository with either fakes or mocks to test the different cases. Basics of manual dependency injection. This section covers how to apply manual dependency injection in a real Android app scenario.

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

How to manually clear a specific viewmodel?, If you check the code here you'll find out, that you can get the ViewModelStore from a ViewModelStoreOwner and Fragment , FragmentActivity  It will list all the apps, along with how much space each app is occupying. Depending on the version or skin running on top of Android, you might also find an option to sort apps alphabetically or

If you don't want the ViewModel to be scoped to the Activity lifecycle, you can scope it to the parent fragment's lifecycle. So if you want to share an instance of the ViewModel with multiple fragments in a screen, you can layout the fragments such that they all share a common parent fragment. That way when you instantiate the ViewModel you can just do this:

CommonViewModel viewModel = ViewModelProviders.of(getParentFragment()).class(CommonViewModel.class);

Hopefully this helps!

Manually clearing an Android ViewModel? – Icetutor, 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  From the above illustration, we can say that the ViewModel is available throughout the life cycle of an Activity or a Fragment. So, the Android system may call the onCreate() method a number of times, but the ViewModel is there for the application throughout its life cycle.

I think I have a better solution.

As stated by @Nagy Robi, you could clear the ViewModel by call viewModelStore.clear(). The problem with this is that it will clear ALL the view model scoped within this ViewModelStore. In other words, you won't have control of which ViewModel to clear.

But according to @mikehc here. We could actually create our very own ViewModelStore instead. This will allow us granular control to what scope the ViewModel have to exist.

Note: I have not seen anyone do this approach but I hope this is a valid one. This will be a really good way to control scopes in a Single Activity Application.

Please give some feedbacks on this approach. Anything will be appreciated.

Update:

Since Navigation Component v2.1.0-alpha02, ViewModels could now be scoped to a flow. The downside to this is that you have to implement Navigation Component to your project and also you have no granualar control to the scope of your ViewModel. But this seems to be a better thing.

How to clear value of LiveData with Transformations from regular , r/androiddev: News for Android developers with the who, what, where when and This is huge issue, and we don't know how to clear LiveData after Viewmodel gets LiveData is supposed to hold the data until it is manually cleared/process​  public final void clear() { for (ViewModel vm : mMap.values()) { vm.onCleared(); } mMap.clear(); } now, maybe you have know it. just like the picture above. When the fragment finished, it cleared; when activity recreate,the fragment's onDestroy() will not be invoked, because

Manually clearing an Android ViewModel?, With reference to the android.arch.lifecycle.ViewModel class. How can one manually clear a ViewModel from it's ViewModelStore or holder fragment? It is not advisable to use Android framework classes inside ViewModels. Here is the link on Google Developers blog post with the detailed explanation: ViewModels and LiveData: Patterns + AntiPatterns. Ideally, ViewModels shouldn’t know anything about Android. This improves testability, leak safety and modularity.

ViewModel's onCleared is not be call after fragment is destroyed , I have a very simple ViewModel. class TestViewModel: ViewModel() { override fun onCleared() Log.d("TEST", "clear") } } and I use it in a fragment class If I want the method to be called, I have to remove fragment manually https://​developer.android.com/topic/libraries/support-library/revisions.html. ViewModel Overview Part of Android Jetpack. The ViewModel class is designed to store and manage UI-related data in a lifecycle conscious way. The ViewModel class allows data to survive configuration changes such as screen rotations. Note: To import ViewModel into your Android project, see the instructions for declaring dependencies in the

ViewModel Overview, When the owner activity is finished, the framework calls the ViewModel objects's onCleared() method so that it can clean up resources. Caution:  View-ViewModel interactions LiveData beyond the ViewModel. The observable paradigm works really well between the View controller and the ViewModel, so you can use it to observe other components of

ViewModelStore, belongs to Maven artifact android.arch.lifecycle:viewmodel:1.1.1 then it should call clear() on this ViewModelStore , so ViewModels would be  The android.arch Architecture Components packages are no longer maintained. They have been superseded by the corresponding androidx.* packages. See androidx.lifecycle.MutableLiveData instead.

Comments
  • related: Shared ViewModel lifecycle for Android JetPack
  • Hey! How about creating your own retained fragment and scoping your viewmodel to that retained fragment? Now, you have total control on the lifecycle of your viewmodel. You just need to make the activity add or remove the fragment if needed and wire the retained fragment and other fragments together through the activity. It does sounds like writing some boiler plate code though but I wanna know what you think.
  • I have no idea if it's ok to use getTargetFragment() for scope: ViewModelProvider(requireNotNull(targetFragment)).get(MyViewModel::class.java)
  • Yes, there is a way to do so, I have explained it here
  • Very nice, I was looking in this direction but missed the obvious part that, as you say "FragmentActivity ... implements, that interface [ViewModelStoreOwner]".
  • Ok so we could clear the ViewModel manually but is it a good idea? If I clear the view model through this method is there anything i should look after or made sure i did correctly?
  • I also noticed you could not clear only a specific viewmodel which should be the case. If you call viewmodelstoreowner.clear() all stored viewmodel will be cleared.
  • A word of warning with this, if you're using the new SavedStateViewModelFactory to create a particular view model you will need to call savedStateRegistry.unregisterSavedStateProvider(key) - the key being the one you should use when you call ViewModelProvider(~).get(key, class). Otherwise if you attempt to get (ie. create) the viewmodel in future you will get IllegalArgumentException: SavedStateProvider with the given key is already registered
  • It works like a charm! You saved my day. Thanks...
  • What you write is true, but this is for a case where I do want to scope it to the Activity lifecycle, specifically to share it between multiple fragments that may not be displayed at the same time. This is a good response in the other case that I mentioned and I think I must update my question to remove that case (as it creates confusion - apologies for that)