6

Is there a minimum time LiveData needs to propagate the data upstream?

I have a MutuableLiveData which is updated from a repository. The updating code loads some data from the internet and sets the value of the MutuableLiveData. The downloading happens on one or more workerThreads and a callback is being made to the repository with the downloaded data. Here is relevant code. I used synchronized to prevent the threads from trying to change the variable at the same time.

In the repository:

@Override
public void returnResult(Schedule scheduleToReturn) {
     synchronized(this){
     mSecondaryWeekSchedule.postValue(scheduleToReturn)};
}

And in the fragment:

mScheduleViewModel.getOverlayWeekSchedule().observe(getViewLifecycleOwner(), new Observer<Schedule>() {
        @Override
        public void onChanged(@Nullable Schedule schedule) {
            Log.d(DEBUGTAG, "Overlay weekschedule changed");
            Log.d(DEBUGTAG, ""+schedule.toString());
            addOverlay(schedule);
        }
    });

The getOverlayWeekSchedule just links to the liveData variable in the repository. Setting appropiate Log.d() in the repository I find this:

08-20 21:11:25.982 3001-3049/nl.kl_solutions.schedulecompareforzermelo D/ScheduleRepository: schedule returned:Owner:hym WeekStart:03 Sep Events:19 08-20 21:11:26.015 3001-3065/nl.kl_solutions.schedulecompareforzermelo D/ScheduleRepository: schedule returned:Owner:6409 WeekStart:03 Sep Events:27 08-20 21:11:26.348 3001-3001/nl.kl_solutions.schedulecompareforzermelo D/WeekScheduleFragment: Overlay weekschedule changed 08-20 21:11:26.349 3001-3001/nl.kl_solutions.schedulecompareforzermelo D/WeekScheduleFragment: Owner:6409 WeekStart:03 Sep Events:27

The first two lines are from,the repository showing the schedules returned through the callback to the repository on different threads. The last two lines are one firing of the observer in the fragment, showing only the change to the last schedule is recorded. The first change is lost somewhere.

2 Answers 2

16

By design if you called postValue multiple times before the main thread executes a posted task, only the last value would be dispatched.

https://developer.android.com/reference/android/arch/lifecycle/LiveData.html#postValue(T)

There is the alternative setValue method which doesn't use a post operation - to use this you would need to ensure it's called on the main thread.

3
  • Now using a handler on the main thread to set the value and both schedules are coming through. Thanks
    – KvdLingen
    Commented Aug 21, 2018 at 17:48
  • 1
    wasted half of my day on this :-( Commented Nov 7, 2020 at 14:39
  • Google is doing their job again :)
    – Farid
    Commented Oct 20, 2021 at 8:08
9

Like Chris said, you have to use setValue to get all events. But you can use Kotlin's coroutines instead of postValue for this, then you will get all the changes easily (and it's a simply refactor):

//make sure you have a CoroutineScope to be able to use 'launch'
launch (Dispatchers.Main){ 
    yourMutableLiveData.value = "YourValueHere" 
}
1
  • The original program is written in Java and CoRoutines were not available at the time. I am rewriting in Kotlin so CoRoutines are definitely being used.
    – KvdLingen
    Commented Jul 19, 2020 at 10:43

Not the answer you're looking for? Browse other questions tagged or ask your own question.