We use LiveData to observe data inside ViewModel from an Activity or Fragment. If any change or update to this data happens, we can automatically update the Activity or Fragment.
LiveData only updates observers in an active lifecycle state. Its benefits are to automatically update the UI when app data changes.
LiveData vs MutableLiveData
Data inside LiveData is read-only. It cannot be updated as it has no public method to modify it. MutableLiveData can be updated.
Implementation
Add the following into your App’s gradle.build
dependencies {
def lifecycle_version = "2.1.0"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
}
We have the following ViewModel.
class MainActivityViewModel(startingTotal: Int): ViewModel {
var total = MutableLiveData<Int>()
init {
total.value = startingTotal
}
fun setTotal(input: Int) { total.value = input }
}
How we use it from another Activity.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ...
viewModel.total.observe(this, Observer {
// this will be executed when MutableLiveData changes.
binding.resultTextView.text = it.toString()
})
button.setOnClickListener { viewModel.setTotal(5) }
}
How to encapsulate LiveData
We want to encapsulate total
, as leaving it public is no good design.
- We mark it as
private
. - We need to declare a new public variable. As we’re not going to edit it, it should be
LiveData
. We can use Kotlin backing property to returnLiveData
from a getter function.
class MainActivityViewModel(startingTotal: Int): ViewModel {
private var total = MutableLiveData<Int>()
val totalData: LiveData<Int>
get() = total
init {
total.value = startingTotal
}
fun setTotal(input: Int) { total.value = input }
}
Now we may change the onCreate()
method.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ...
viewModel.totalData.observe(this, Observer {
// this will be executed when MutableLiveData changes.
binding.resultTextView.text = it.toString()
})
button.setOnClickListener { viewModel.setTotal(5) }
}