When I observe from Fragment A a variable in my viewmodel
val fetchTopicsList = liveData(Dispatchers.IO) {
emit(Resource.Loading())
try {
emit(repo.getIdeas())
}catch (e:Exception){
emit(Resource.Failure(e))
}
}
And I navigate to Fragment B and come back to Fragment A the observer will fire again but the new data will not be fetched.
Now, if I change that declaration to a function declaration
fun fetchTopicsList() = liveData(Dispatchers.IO) {
emit(Resource.Loading())
try {
emit(repo.getIdeas())
}catch (e:Exception){
emit(Resource.Failure(e))
}
}
When I do the same (go from Fragment A to Fragment B and come back) the observer will trigger again and pull the data again from the server.
Why the function fires again while the variable just keeps the first fetched data ?
You probably actually want a single instance of MutableLiveData
which emits on some interaction, but I want to directly address your question:
With the function, each invocation will give you a new instance of LiveData
, whereas using a property initializer will instantiate + set it to a single instance of LiveData
when your class is instantiated. This means that if your property is on a ViewModel
it will survive through configuration changes and pause / resume cycles until it is destroyed.
If you prefer the property syntax, you can make it do the same thing as when reinvoking the function each time, by overriding the getter, but honestly a function is more syntactically accurate here.
This is how you would achieve the same functionality with property syntax:
val fetchTopicsList: LiveData<..>
get() = liveData(Dispatchers.IO) {
emit(Resource.Loading())
try {
emit(repo.getIdeas())
} catch (e:Exception){
emit(Resource.Failure(e))
}
}
Again, a better approach is probably a single MutableLiveData
and exposing a function on ViewModel
to make the request and post the value for any subscribers though.