Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android LiveData: Not receiving all notifications

I'm experimenting with Android's LiveData. I just tried to push a lot of notifications to an observer that observes a LiveData object. I let a thread run in background and in a while-loop i constantly push random values via LiveData's postValue-method. The number of received notifications (number of onChanged()-callbacks) in the observer which observes the livedata is much less then the number of calls of postValue in the background thread.

Can somebody explain what's the reason for this?

Thank you in advance

like image 725
MarcWho Avatar asked Jun 25 '18 20:06

MarcWho


1 Answers

The explanation lies in the implementation for postValue and mPostValueRunnable:

protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        //this is true on the first run or right after the observer receives an update
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    // this statement will be true if the observer hasn't received an update even though it's sent to the main looper
    if (!postTask) { 
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

private final Runnable mPostValueRunnable = new Runnable() {
    @Override
    public void run() {
        Object newValue;
        synchronized (mDataLock) {
            newValue = mPendingData;
            mPendingData = NOT_SET;//once this value is reset a new mPostValueRunnable can be sent
        }
        // here the observer will receive the update
        setValue((T) newValue);
    }
};  
  1. On the first run, in postValue mPendingData = NOT_SET so the following if (!postTask) condition is false and thus mPostValueRunnable is sent to the main thread.
  2. On the second run, if the mPostValueRunnable hasn't been executed yet (it may not as values are updated extremely frequently), the if is true and so nothing is sent to the main thread except that mPendingData is set to a new value.
  3. On the third run, it can be the same as on the previous one and so on for some number of updates. Thereof, until mPostValueRunnable actually runs and resets mPendingData to NOT_SET, all the update values are lost except for the last one. In this case, only one update comes via Observer with the latest value.
like image 199
Anatolii Avatar answered Nov 09 '22 03:11

Anatolii