With the stabilization of Android Architecture Components I started updating all my basic ViewModel
s to the new implementation ofViewModel
. In my understanding, the usage of LiveData
is recommended to hold the Model
class since it handles the lifecycle better.
I like using Data Binding
because it makes the code clearer in Java/Kotlin side and it is not needed to "watch" the value changes to update the UI. However the layout using Data Binding
only watch data changes if the Model
(or the ViewModel) extends BaseObservable
and LiveData
does not. I understand the one of the main objectives of LiveData
is to be observed and updates the UI programmatically but for simple updates, Data Binding
is very useful.
This issue was already reported (GitHub and Stack Overflow) and first was said that the version 1.0 would have it and now is said that this feature is in development.
In order to use both LiveData
and Data Binding
, I created a very simple implementation of class that extends BaseObservable
:
import android.arch.lifecycle.LiveData
import android.arch.lifecycle.MutableLiveData
import android.databinding.BaseObservable
class ObservableMutableLiveData<T>() : BaseObservable() {
private var data: MutableLiveData<T> = MutableLiveData()
constructor(data: T) : this() {
this.data.value = data
}
public fun set(value: T) {
if (value != data.value) {
data.value = value
notifyChange()
}
}
public fun get(): T? {
return data.value
}
public fun getObservable(): LiveData<T> {
return data
}
}
So basically my ObservableMutableLiveData
is a copy of ObservableField
using LiveData
to store the model and with this implementation, the layout updates after every model update.
The questions are:
LiveData
? Does this wrapper "breaks" the functionalities of LiveData
, such as be lifecycle-aware?LiveData
is the new ObservableField
. Is this correct?For those who came across this question looking for an example like I did, here's one:
In layout .xml
put the LiveData
element with it's type:
<layout>
<data>
<variable
name="myString"
type="android.arch.lifecycle.MutableLiveData<String>"/>
</data>
...
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{myString}'
...
/>
...
</layout>
In your code set it's value and the lifecycle owner:
MutableLiveData<String> myString = new MutableLiveData<>();
...
binding.setLifecycleOwner(this);
binding.setMyString(myString);
That's it :)
Note that the default value of LiveData
elements is null
so assign initial values to make sure you get the desired effect right away or use this to enforce nullability.
EDIT:
Use androidx.lifecycle.MutableLiveData<String>
as type if you use androidx
.