I have some more complex logic for data provided by my ViewModel
to the UI, so simply exposing the data via LiveData
won't do the job for me. Now I've seen in the Android docs that I can implement Observable
on my ViewModel
to get the fine-grained control I need.
However in the documentation it also says:
There are situations where you might prefer to use a ViewModel component that implements the Observable interface over using LiveData objects, even if you lose the lifecycle management capabilities of LiveData.
How intelligent is the built-in Android data binding? Will it automatically unregister it's listeners when necessary (e.g. on configuration changes where the View is destroyey) so that I don't have to care about the lost lifecycle capabilities? Or do I have to watch the Lifecycle of the View and unregister it's listeners? (=do manually what LiveData normally does for me).
How intelligent is the built-in Android data binding? Will it automatically unregister it's listeners when necessary (e.g. on configuration changes where the View is destroyey) so that I don't have to care about the lost lifecycle capabilities? Or do I have to watch the Lifecycle of the View and unregister it's listeners? (=do manually what LiveData normally does for me).
So I did some tests. I implemented androidx.databinding.Observable
on my ViewModel
and did a configuration change with the following log calls:
override fun removeOnPropertyChangedCallback(
callback: androidx.databinding.Observable.OnPropertyChangedCallback?) {
Log.d("APP:EVENTS", "removeOnPropertyChangedCallback " + callback.toString())
}
override fun addOnPropertyChangedCallback(
callback: androidx.databinding.Observable.OnPropertyChangedCallback?) {
Log.d("APP:EVENTS", "addOnPropertyChangedCallback " + callback.toString())
}
I saw that addOnPropertyChangedCallback
was invoked for each time my viewmodel was referenced in a layout binding expression. And not once did I see removeOnPropertyChangedCallback
invoked. My initial conclusion is that AndroidX databinding is dumb and does not automagically remove the listener.
FYI: the callback type was ViewDataBinding.WeakPropertyListener
However, I took a peek at ViewDataBinding.java
source code and found that it is using Weak References to add the listener.
So what this implies, is that upon a configuration change, Android OS should be able to garbage collect your Activity/Fragment because the viewmodel does not have a strong reference.
My advice: Don't add the boilerplate to unregister the listeners. Android will not leak references to your activities and fragments on configuration changes.
Now, if you choose not to use LiveData
, consider making your viewmodel implement LifecycleObserver
so that you can re-emit the most recent value when your Activity/Fragment goes into the active state. This is the key behavior you lose by not using LiveData
. Otherwise, you can emit notifications by using the PropertyChangeRegistry.notifyCallbacks()
as mentioned in the documentation you shared at some other time. Unfortunately, I think this can only be used to notify for all properties.
Another thing... while I've not verified the behavior the source code seems to indicate that weak references are used for ObservableField
, ObservableList
, ObservableMap
, etc.
LiveData
is different for a couple of reasons:
LiveData.observe
says that a strong reference is held to both the observer AND the lifecycle owner until the lifecycle owner is destroyed.LiveData
emits differently than ObservableField
. LiveData
will emit whenever setValue
or postValue
are called without regard to if the value actually changes. This is not true for ObservableField
. For this reason, LiveData
can be used to send a somewhat "pseudo-event" by setting the same value more than once. An example of where this can be useful can be found on the Conditional Navigation page where multiple login failures would trigger multiple snackbars.