Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Observing repository LiveData from ViewModel and notify UI

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

}
like image 426
droidrcc Avatar asked Feb 04 '18 02:02

droidrcc


People also ask

How do you communicate between ViewModel and Repository?

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.

Can a ViewModel observe LiveData?

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?

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.

How would a repository work with livedata?

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:

Is it possible to observe livedata changes in a ViewModel?

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.

Can I observe on data from the repository W/ observeforever?

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.

How do I observe a livedata object in data binding?

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.


1 Answers

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.

like image 176
Fabio Collini Avatar answered Nov 15 '22 00:11

Fabio Collini