Google says that is not possible to observe a LiveData from a ViewModel:
[...] However ViewModel objects must never observe changes to lifecycle-aware observables, such as LiveData objects.[...]
And I would handle the repo.login()
result in the ViewModel and notify the UI thought the two SingleLiveEvents, is it possible?
class Repository {
// .... //
fun login(user:String, password:String): LiveData<Status> { /* ... */ }
}
class LoginViewModel : ViewModel() {
@Inject
lateinit var repo: Repository
private var auth = MutableLiveData<User>()
private var showErrorEvent = SingleLiveEvent<String>()
private var showSuccessEvent = SingleLiveEvent<String>()
// Called from UI
fun performLogin(user:User){
repo.login(user.name, user.password)
// We can't observe the result here
// and update error/success events
}
// Called from UI
fun getErrorEvent() = showErrorEvent
// Called from UI
fun getSuccessEvent() = showSuccessEvent
}
Just use HTTP status code. In response you'll get status code, just send it to viewmodel and in viewmodel you can easily send it to Activity or fragment by observing it.
ViewModel allows the app's data to survive configuration changes. In this codelab, you'll learn how to integrate LiveData with the data in the ViewModel . The LiveData class is also part of the Android Architecture Components and is a data holder class that can be observed.
Why should you initialize and store LiveData in your ViewModel instead of a UI Controller? Both the ViewModel and LiveData are lifecycle aware. To ensure that the LiveData isn't destroyed when the UI Controller is destroyed. To hide or separate implementation details making your app more flexible.
The repositories would connect to data sources and expose LiveData. The ViewModels would then expose the LiveData to the UI Layer. Our setup visualised. Now — there are some issues with this, like the actually unneeded abstraction — but we won’t look at that here. Here’s what a typical Repository would look like:
However ViewModel objects must never observe changes to lifecycle-aware observables, such as LiveData objects. [...] In this ViewModel that should be used as sample, you are doing it. What's important is you don't observe on a LiveData object from something bound to a different lifecycle.
If the activity scoped one binds to a livedata object from the fragment one, the fragment's ViewModel will still be referenced even though it is no longer managed. It is OK to observe on data from the repository w/ observeForever as this isn't bound to a lifecycle.
You can now use a LiveData object as an observable field in data binding expressions. The ViewDataBinding class now includes a new setLifecycle method that you need to use to use to observe LiveData objects. ViewModel objects can contain LifecycleObservers, such as LiveData objects.
I think that the official guideline is to combine multiple livedatas in the ViewModel using a transformation. However usually I prefer to use livedatas only in the communication between the ViewModel and the View, in the repositories I use RxJava or coroutines. So in your example I'd modify the login
method in the repository to return a Single
instead of a livedata and subscribe to it in the ViewModel. You can then cancel the subscription when the ViewModel is destroyed. You can find an example of this architecture in this repository.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With