Difference of setValue() & postValue() in MutableLiveData

AndroidAndroid LivedataMutablelivedata

Android Problem Overview


There are two ways that make change value of MutableLiveData. But what is difference between setValue() & postValue() in MutableLiveData.

I could not find documentation for same.

Here is class MutableLiveData of Android.

package android.arch.lifecycle;

/**
 * {@link LiveData} which publicly exposes {@link #setValue(T)} and {@link #postValue(T)} method.
 *
 * @param <T> The type of data hold by this instance
 */
@SuppressWarnings("WeakerAccess")
public class MutableLiveData<T> extends LiveData<T> {
    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}

Android Solutions


Solution 1 - Android

Based on the documentation:

setValue():

> Sets the value. If there are active observers, the value will be > dispatched to them. This method must be called from the main thread.

postValue():

> Posts a task to a main thread to set the given value. If you called this method multiple times before a main thread executed a posted task, only the last value would be dispatched.

To summarize, the key difference would be:

setValue() method must be called from the main thread. But if you need set a value from a background thread, postValue() should be used.

Solution 2 - Android

All of the above answers are correct. But one more important difference. If you call postValue() and after that you call getValue(), you may not receive the value that you set in postValue(). If the main thread had already set the value, then you will get the value that you posted, but if the main thread hadn't set the value yet, then you don't get the value that you posted. So be careful if you work in background threads.

Solution 3 - Android

setValue() is called directly from caller thread, synchronously notifies observers and changes LiveData value immediately. It can be called only from MainThread.
postValue() uses inside something like this new Handler(Looper.mainLooper()).post(() -> setValue()), so it runs setValue via Handler in MainThread. It can be called from any thread.

Solution 4 - Android

setValue()

>Sets the value. If there are active observers, the value will be dispatched to them.

>This method must be called from the main thread.

postValue

>If you need set a value from a background thread, you can use postValue(Object)

>Posts a task to a main thread to set the given value.

>If you called this method multiple times before a main thread executed a posted task, only the last value would be dispatched.

Solution 5 - Android

This is not a direct answer to the above problem. The answers from Sagar and w201 are awesome. But a simple rule of thumb I use in ViewModels for MutableLiveData is:

private boolean isMainThread() {
    return Looper.myLooper() == Looper.getMainLooper();
}

private MutableLiveData<Boolean> mutVal = new MutableLiveData<>(false);
public LiveData<Boolean> getMutVal() { return this.mutVal;  }
public void setMutVal(boolean val) {
    if (isMainThread()) mutVal.setValue(val);
    else mutVal.postValue(val);
}

Replace mutVal with your desired value.

Solution 6 - Android

setValue() method must be called from the main thread. If you need to set a value from a background thread, you can use postValue().

More here.

Solution 7 - Android

TL; DR

  • If you are working on the main thread, then both setValue and postValue will work in the same manner i.e. they will update the value and notify the observers.

  • If working in some background thread, then you can't use setValue. You have to use postValue here with some observer. More here

Solution 8 - Android

In our app, we had used single LiveData that contains data for multiple views in an activity/screen. Basically N no of datasets for N no of views. This troubled us a bit because the way postData is designed for. And we have state object in LD that conveys to view about which view needs to be updated.

so LD looks like this:

LD {
   state (view_1, view_2, view_3 …),
   model_that_contains_data_of_all_views
}

There are couple of views (view_1 and view_2) that had to be updated when one event occurs..mean they should get notified at the same time when event occurs. So, I called:

postData(LD(view_1, data))
postData(LD(view_2, data)

This would not work for reasons we know.

What I understood is that basically one LD should represent only one view. Then there is no chance that you would've to call postData() twice in a row. Even if you call, the way postData handles it for you is what you would also expect (showing latest data for you in view). Everything fall well in place.

> One LD -> one View. PERFECT > > One LD -> multiple views THERE MAY BE A WEIRD BEHAVIOR

Solution 9 - Android

If setting the value will take a long time (if you have to retrieve additional data from a remote source that could be slow to respond, for example), use postValue() so you don't lock up the main thread.

When setting the value is guaranteed to be fast (as it most often is), setValue() is simplest and best.

Solution 10 - Android

postValue - can be used from anywhere

setValue - only from main/UI thread

Basically, postValue should be used only from background thread as it might be slower compared to setValue, which reacts faster.

I've wrote a snippet that handles both case:

/**
 * Live data thread-safe set-value
 * Context: https://stackoverflow.com/a/52227632/6688493
*/
fun <T> MutableLiveData<T>.assignValue(newValue: T){

    if(Looper.myLooper() == Looper.getMainLooper()) {
        this.value = newValue
    }
    else {
        this.postValue(newValue)
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKhemraj SharmaView Question on Stackoverflow
Solution 1 - AndroidSagarView Answer on Stackoverflow
Solution 2 - Androidw201View Answer on Stackoverflow
Solution 3 - AndroidUfkokuView Answer on Stackoverflow
Solution 4 - AndroidAskNileshView Answer on Stackoverflow
Solution 5 - AndroidHimujjalView Answer on Stackoverflow
Solution 6 - AndroidLevon PetrosyanView Answer on Stackoverflow
Solution 7 - AndroidAman GargView Answer on Stackoverflow
Solution 8 - AndroidcgrView Answer on Stackoverflow
Solution 9 - AndroidDavid VancinaView Answer on Stackoverflow
Solution 10 - Androidtouhid udoyView Answer on Stackoverflow