Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change value of LiveData and not notify the observers

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?

like image 968
Morteza Rastgoo Avatar asked Dec 08 '22 12:12

Morteza Rastgoo


2 Answers

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.

like image 148
ssynhtn Avatar answered Dec 11 '22 09:12

ssynhtn


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");
like image 25
SSB Avatar answered Dec 11 '22 09:12

SSB