Why Observers added as observeForever to LiveData must be removed?

From what I understood from the documentation, I should remove the observer everytime the view that instantiates the ViewModel

To achieve this you should instantiate your viewmodel inside the View (Activity, Fragment) and observe the livedata like this

val model = ViewModelProviders.of(this).get(MyViewModel::class.java)
        model.getUsers().observe(this, Observer<List<User>>{ users ->
            // update UI
        })

by passing this you tie observing livedata to view's lifecycle, so when View (Activity, Fragment) will be destroyed both viewmodel and observer will be destroyed.


"I should remove the observer everytime the view that instantiates the ViewModel (with the previous code) was destroyed, right?"

If you are obsering a LiveData in ViewModel using observeForever(observer):

  • You should not worry about View's lifecycle, because it is different from ViewModel's life. ViewModel should be able to out-live the View that creates it. Instead, the framework will call onCleared() when the ViewModel is not needed, so that's where you should handle removing the observer.

If you are observing a LiveData in View using observe(lifecyclerowner, observer)

  • Observers will automatically removed by the framework when the lifecycleowner is destroyed.


"But shouldn't the Observers be destroyed once the view is destroyed (since the ViewModel instance was instantiated in the view and will also be destroyed)?"

This question is more of a Java question than Android.

Think about what it means by "being destroyed". When a View or ViewModel is destroyed by the Android Framework, it does not mean that the object is completely removed from the memory. Your activities and fragments will not be garbage collected as long as there are other objects (such as observer) that has reference to them.

If you call observe(activity, observer), then the Android Framework can track the connection between the activity instance and the observer instance, and therefore it can kill observer when it wants to kill activity. However if you simply call observeForever(observer) there is simply no way for Android Framework to tell which object this observer belongs to.


Implementing Sanlok Lee's answer in a ViewModel, it would look like this:

val password by lazy {
    MutableLiveData<String>()
}

private val passwordObserver = Observer<String> {
    ...
}

init {
    initObservable()
}

private fun initObservable() {
    password.observeForever(passwordObserver)
}

override fun onCleared() {
    password.removeObserver(passwordObserver)
    super.onCleared()
}