In some cases, I want to change the value of LiveData and don't want the observers to notify about the change. How can I do that?
In some cases, I want to change the value of LiveData and don't want the observers to notify about the change. How can I do that?
I would just use Pair<T, Boolean> as the value type, and the observers can check pair.second
The idea is simple. Replace your MutableLiveData<String> with MutableLiveData<Pair<String, Boolean>>
When you want to notify the observers with value s, just call liveData.setValue(new Pair(s, true)) and call liveData.setValue(new Pair(s, false)) otherwise
on the observer side, just check the pair.second to distinguish these two cases
Edit: I was using phone to answer the question and it seems stackoverflow hides characters surrounded by angle brackets.
I think my custom class will help you
import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.LifecycleOwner;
import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.Observer;
import android.support.annotation.MainThread;
import android.support.annotation.NonNull;
import android.util.Pair;
import java.util.ArrayList;
import java.util.List;
public class SSBLiveData<T> extends MutableLiveData<T> {
private List<Pair<LifecycleOwner, Observer>> observers = new ArrayList<>();
@MainThread
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull final Observer observer) {
observers.add(new Pair<>(owner, observer));
super.observe(owner, observer);
}
@MainThread
private void resetAllObservers() {
for (Pair<LifecycleOwner, Observer> observer : observers) {
super.observe(observer.first, observer.second);
}
}
@MainThread
private void removeAllObservers() {
for (Pair<LifecycleOwner, Observer> observer : observers) {
removeObservers(observer.first);
}
}
@MainThread
void setValueWithoutNotify(T value) {
removeAllObservers();
super.setValue(value);
System.out.println("Not notifying value " + getValue());
}
// For androidx use this method
/*@MainThread
@Override
public void removeObserver(@NonNull Observer<? super T> observer) {
for (Pair<LifecycleOwner, Observer> observerItem : observers) {
if (observerItem.second.equals(observer) && observerItem.first.getLifecycle().getCurrentState() == Lifecycle.State.DESTROYED) {
observers.remove(observerItem);
}
}
super.removeObserver(observer);
}*/
@MainThread
@Override
public void removeObserver(@NonNull Observer<T> observer) {
for (Pair<LifecycleOwner, Observer> observerItem : observers) {
if (observerItem.second.equals(observer) && observerItem.first.getLifecycle().getCurrentState() == Lifecycle.State.DESTROYED) {
observers.remove(observerItem);
}
}
super.removeObserver(observer);
}
@Override
public void setValue(T value) {
super.setValue(value);
if (!hasObservers()) {
resetAllObservers();
}
}
}
Use it this way
SSBLiveData<String> liveData = new SSBLiveData<>();
liveData.setValueWithoutNotify("It won't get notified");
liveData.setValue("It will get notified");
The same class described in the accepted answer but overridden in the Kotlin and with AndroidX imports:
import android.util.Pair
import androidx.annotation.MainThread
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import java.util.*
class ExtendedLiveData<T>() : MutableLiveData<T>() {
private val observers: MutableList<Pair<LifecycleOwner, Observer<in T>>> = ArrayList()
@MainThread
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
observers.add(Pair(owner, observer))
super.observe(owner, observer)
}
@MainThread
private fun resetAllObservers() {
for (observer in observers) {
super.observe(observer.first, observer.second)
}
}
@MainThread
private fun removeAllObservers() {
for (observer in observers) {
removeObservers(observer.first)
}
}
@MainThread
fun setValueWithoutNotify(value: T) {
removeAllObservers()
super.setValue(value)
println("Not notifying value " + getValue())
}
@MainThread
override fun removeObserver(observer: Observer<in T>) {
for (observerItem in observers) {
if (observerItem.second == observer && observerItem.first.lifecycle
.currentState == Lifecycle.State.DESTROYED
) {
observers.remove(observerItem)
}
}
super.removeObserver(observer)
}
override fun setValue(value: T) {
super.setValue(value)
if (!hasObservers()) {
resetAllObservers()
}
}
fun resetValue() {
super.setValue(null)
}
}