How to manually destroy a shared ViewModel


I’ve a ViewModel in my Android app that is shared by two fragments and is therefore given the scope of Activity.

The thing is that this shared ViewModel would stay alive will all the data that it contains, even after the fragments are detached, until the Activity it is scoped to is destroyed.

So, is there a way to destroy such ViewModel manually?

There is no means to do that, sorry.

Either the activity needs the data, or it does not. If it does, then the activity-scoped ViewModel is a good thing, and keeping it alive is a good thing.

If it does not, then the next question is: how big is the unique data (i.e., data that is not already referenced elsewhere, such as in a cache)? If it is large — say, hundreds of KB — then perhaps it is something that you need to worry about. Conversely, if the data is small, I would not worry about it unless you were encountering some specific problems.

But, if in the end you conclude that you do need to do something, I know of only three options:

  1. Do something other than a shared viewmodel. For example, there is the FragmentResult system. It’s only in alpha, and I have not used it, but it is an option for passing data between fragments.

  2. See if you can find a tighter-scoped ViewModelStoreOwner. For example, the Navigation component allows you to scope a ViewModel to a navigation graph, so perhaps you could arrange for a nested navigation graph for these two fragments.

  3. Something that knows about when these fragments come and go (probably the activity) tells the viewmodel to flush its caches when both of those fragments are gone.

Flush the cache? Is there a way to do this?

Well, it depends a lot of what is in this ViewModel. Your problem, as I understand it, is that you do not want to hold onto data. So, you need to set up your ViewModel so you can have it stop holding onto data when you ask it to:

  • If you have nullable var properties, set them to null
  • If you have var properties that hold an object from some sealed class, set them to a value that does not hold anything large
  • If you have MutableLiveData, post null or something lightweight to it
  • And so on

Hmm, makes sense. I’ll do that. Thanks!