15

Before Lifecycle and LiveData stuff, Viewmodel could observe changes to its own observables quite easily. It was only a matter of subscribing to Observable*'s changes and react to them. Then one might used a two-way binding to react immediately on user's input.

In Android Studio Canary, it is now allowed to bind to LiveData objects, provided that Binding knows lifecycle of its owner (ViewBinding now has additional setLifecycle method), by Android Studio Canary information:

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.

However, Viewmodel documentation states clearly:

ViewModel objects can contain LifecycleObservers, such as LiveData objects. However ViewModel objects must never observe changes to lifecycle-aware observables, such as LiveData objects.

(emphasis mine)

So how one can react immediately to LiveData changes if ViewModel cannot subscribe to them?

And, furthermore, why Viewmodel can not observe changes to its own LiveData?

Sagar
  • 23,903
  • 4
  • 62
  • 62
Spook
  • 25,318
  • 18
  • 90
  • 167
  • @pskink It is enough to propagate data between viewmodel and view. What I'm interested in is to capture changes in the data. For instance, user changes checkbox state and I want to react to that and perform an operation. How should I do that? – Spook Jan 06 '18 at 13:37
  • @pskink how `LiveData.setValue` allows me to get information, that user changed something in UI? – Spook Jan 06 '18 at 19:42
  • @pskink This does not matter. View may as well set them manually, but I need to capture changes in ViewModel to react to them immediately. How can I do that without subscribing to LiveData from ViewModel? – Spook Jan 09 '18 at 06:24
  • @pskink As I said, **this does not matter**. View may as well set the Livedata manually, from code. What's important is that I want to listen to those changes in ViewModel, so that I may react to them. How can I do that? – Spook Jan 10 '18 at 08:17
  • use mediatorlivedata – Sagar Nayak Jan 25 '18 at 13:22
  • Check if this helps: https://stackoverflow.com/a/49000792/561259 – Desmond Lua Feb 27 '18 at 04:32
  • u can use MediatorLiveData in this case .Reference =https://developer.android.com/reference/android/arch/lifecycle/MediatorLiveData – SIVAKUMAR.J Mar 08 '19 at 07:02

2 Answers2

5

I fixed this issue using MediatorLiveData. You can follow the steps below.

  1. Create a variable (ex. result).

    private final MediatorLiveData<Resource<RequestType>> result = new MediatorLiveData<>();
    
  2. Call addSource method where the first argument is LiveData and the second is an observer.

    LiveData<Resource<EmptyResponse>> observable = service.createItems();
    result.addSource(observable, response -> {
        //Write code here 
    }
    

Also see this SO answer. The basic requirement is almost the same.

Rafa Viotti
  • 9,998
  • 4
  • 42
  • 62
Saurabh Khare
  • 1,227
  • 13
  • 24
3

You can use Transformations to invoke actions if one of your LiveData Objects changes.

E.g. the user selects a person in a Spinner and you want to load the according person object.

MutableLiveData<Integer> personId = new MutableLiveData<>();
LiveData<Person> person = Transformations.switchMap(personId, id -> getPerson(id));
woodii
  • 763
  • 7
  • 23