Ana Paula
Ana Paula

Reputation: 9467

Why Observers added as observeForever to LiveData must be removed?

I've read on Android LiveData documentation that:

You can register an observer without an associated LifecycleOwner object using the observeForever(Observer) method. In this case, the observer is considered to be always active and is therefore always notified about modifications. You can remove these observers calling the removeObserver(Observer) method.

I'm building an app using MVVM architecture pattern using ViewModel and declaring LiveDatas inside my ViewModel class. At my viewModel I have set a observeForever to a LiveData:

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

init {
    initObservable()
}

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

From what I understood from the documentation, I should remove the observer everytime the view that instantiates the ViewModel (with the previous code) was destroyed, right? 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)?

Upvotes: 16

Views: 15590

Answers (3)

Mario Huizinga
Mario Huizinga

Reputation: 826

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()
}

Upvotes: 4

Sanlok Lee
Sanlok Lee

Reputation: 3494

"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.

Upvotes: 26

Levon Petrosyan
Levon Petrosyan

Reputation: 9615

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.

Upvotes: 1

Related Questions