Почему необходимо удалить наблюдателей, добавленных в LiveData в качестве ObserverForever?

Я прочитал в документации Android LiveData, что:

Вы можете зарегистрировать наблюдателя без связанного объекта LifecycleOwner с помощью метода Observer (Observer). В этом случае наблюдатель считается всегда активным и поэтому всегда уведомляется об изменениях. Вы можете удалить этих наблюдателей, вызвав метод removeObserver (Observer).

Я создаю приложение, используя шаблон архитектуры MVVM, используя ViewModel и объявляю LiveDatas внутри моего ViewModel класс. В моей модели viewModel я установил observeForever на LiveData:

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

init {
    initObservable()
}

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

Насколько я понял из документации, я должен удалять наблюдателя каждый раз, когда представление, которое создает экземпляр ViewModel (с предыдущим кодом), было уничтожено, верно? Но не следует ли уничтожать наблюдателей после уничтожения представления (поскольку экземпляр ViewModel был создан в представлении и также будет уничтожен)?


person Ana Paula    schedule 29.04.2019    source источник
comment
Как вы получили этот ViewModel экземпляр? Почему password наблюдается изнутри самого ViewModel?   -  person Pawel    schedule 29.04.2019


Ответы (3)


«Я должен удалять наблюдателя каждый раз, когда представление, которое создает экземпляр ViewModel (с предыдущим кодом), было уничтожено, верно?»

Если вы наблюдаете LiveData в ViewModel с помощью observeForever(observer):

  • Вам не следует беспокоиться о жизненном цикле View, потому что он отличается от жизни ViewModel. ViewModel должен быть в состоянии пережить View, который его создает. Вместо этого платформа будет вызывать onCleared(), когда ViewModel не требуется, поэтому вам следует обработать удаление наблюдателя.

Если вы наблюдаете LiveData в представлении с помощью observe(lifecyclerowner, observer)

  • Наблюдатели будут автоматически удалены фреймворком при уничтожении владельца жизненного цикла.


«Но разве не следует уничтожать наблюдателей после уничтожения представления (поскольку экземпляр ViewModel был создан в представлении и также будет уничтожен)?»

Этот вопрос больше касается Java, чем Android.

Подумайте, что значит «быть уничтоженным». Когда View или ViewModel уничтожается Android Framework, это не означает, что объект полностью удаляется из памяти. Ваши действия и фрагменты не будут собираться сборщиком мусора, пока существуют другие объекты (например, наблюдатель), которые ссылаются на них.

Если вы вызываете observe(activity, observer), тогда Android Framework может отслеживать соединение между экземпляром activity и экземпляром observer и, следовательно, может убить observer, когда захочет убить activity. Однако, если вы просто вызываете observeForever(observer), Android Framework просто не сможет определить, к какому объекту принадлежит этот наблюдатель.

person Sanlok Lee    schedule 29.04.2019

Насколько я понял из документации, я должен удалять наблюдателя каждый раз, когда представление, которое создает экземпляр ViewModel

Чтобы добиться этого, вы должны создать экземпляр своей модели представления внутри представления (действие, фрагмент) и наблюдать за такими данными, как это

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

передавая this, вы привязываете данные наблюдения к view's жизненному циклу, поэтому при уничтожении View (Activity, Fragment) будут уничтожены как модель просмотра, так и наблюдатель.

person Levon Petrosyan    schedule 29.04.2019

Реализуя ответ Санлока Ли в ViewModel, он будет выглядеть так:

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()
}
person Mario Huizinga    schedule 30.04.2021