A, LiveData

1. Two implementations of the LiveData observer wrapper class
(1)ObserverWrapper
 / / the Observer wrapper classes
  private abstract class ObserverWrapper {
        // The actual observer
        final Observer<? super T> mObserver;
        // Is active
        boolean mActive;
        // Data version
        int mLastVersion = START_VERSION;

        ObserverWrapper(Observer<? super T> observer) {
            mObserver = observer;
        }

        abstract boolean shouldBeActive(a);
        // Whether to override the same LifecycleBoundObserver as the bound lifecycle holder
        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }
        // Unbind the LifecycleBoundObserver override from the lifecycle holder
        void detachObserver(a) {}// Active status changes, which update the number of active and trigger a separate data send to the Observer
        void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            changeActiveCounter(mActive ? 1 : -1);
            if (mActive) {
                dispatchingValue(this); }}}Copy the code
ObserverWrapper is an abstract class that contains the actual observer, the active state, the data version of the current observer, and encapsulates methods for state changes, binding to the lifecycle holder, unbinding from the lifecycle holder, and so on. A state change triggers a change in the number of active observers, as well as an operation to synchronize data to the observer that is currently active

Since it is an abstract class, there must be an implementation class, which has two LifecycleBoundObserver and AlwaysActiveObserver

(2) LifecycleBoundObserver and AlwaysActiveObserver
  // The observer bound to the lifecycle holder decides whether it becomes active based on the lifecycle holder's status, and handles the add and remove operations
    class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
      // Lifecycle holder
      @NonNull
        final LifecycleOwner mOwner;
       // constructor
        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
            super(observer);
            mOwner = owner;
        }
        // To determine whether or not the lifecycle holder is active, it is at least state: STARTED and RESUMED
        @Override
        boolean shouldBeActive(a) {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }
        // LifecycleEventObserver implements the LifecycleEventObserver interface, so it can receive state change call-back and remove Observer if the current state is DESTROYED
        @Override
        public void onStateChanged(@NonNull LifecycleOwner source,
                @NonNull Lifecycle.Event event) {
            Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
          // Remove Observer if the lifecycle is already DESTROYED
          if (currentState == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
           // Handle observer state changes
            Lifecycle.State prevState = null;
            while (prevState != currentState) {
                prevState = currentState;
                activeStateChanged(shouldBeActive());
                currentState = mOwner.getLifecycle().getCurrentState();
            }
        }

        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            // Whether it is sensing the life cycle of the same component
            return mOwner == owner;
        }

        @Override
        void detachObserver(a) {
           // Remove the observer from the lifecycle holder
            mOwner.getLifecycle().removeObserver(this); }}// Implement a always active Observer
    private class AlwaysActiveObserver extends ObserverWrapper {

        AlwaysActiveObserver(Observer<? super T> observer) {
            super(observer);
        }

        @Override
        boolean shouldBeActive(a) {
            return true; }}}Copy the code
A.lifecycleboundobserver implements LifecycleEventObserver, so it can be used to bind to LifeCycleOwner to sense LifecycleEventObserver and implement its active state. The current Observer is removed to ensure that no leaks can be stored
B. LifecycleboundobServer overrides isAttachedTo/and detachObserver to handle binding relationships with lifecycle holders
C. ifecycleBoundObserver overrides shouldBeActive to use the lifecycle holder’s state to determine if it shouldBeActive
D. alwaysActiveObserver is simpler, overriding shouldBeActive to say it should always be active
2.LiveData adds two scenarios of the Observer
  // Register observer parameter 1 lifecycle holder parameter 2 observer
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        Return if the current lifecycle holder is in the DESTROYED state
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        // Wrap owner and Observer as LifecycleBoundObserver and aware of the owner lifecycle
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        // If the map is returned with a null value, the map is successfully inserted. If the map is returned with a value, the map already exists
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        // If it has been inserted, and the perceived life cycle is different from the current one and the owner is inconsistent, an exception is thrown
        if(existing ! =null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        // Return if already inserted and already linked
        if(existing ! =null) {
            return;
        }
        // After successful insertion, link with the lifecycle holder and sense the lifecycle changes
        owner.getLifecycle().addObserver(wrapper);
    }
    // Add a always active observer
    @MainThread
    public void observeForever(@NonNull Observer<? super T> observer) {
        assertMainThread("observeForever");
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        // LifecycleBoundObserver will throw an exception if it already exists, because AlwaysActiveObserver has no owner
        if (existing instanceof LiveData.LifecycleBoundObserver) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        // A direct return already exists
        if(existing ! =null) {
            return;
        }
        // The insertion succeeded and the observer state was set to active
        wrapper.activeStateChanged(true);
    }
Copy the code
A. observe input parameter has two LifeCycleOwner and Observer. Internal LifecycleBoundObserver encapsulates Observer and LifeCycleOwner as LifecycleBoundObserver, so that the lifecycle awareness can be used to determine data distribution. This is how LiveData can sense the life cycle; After a component lifecycle change, the Observer changes its active state to determine whether to distribute data to the Observer
B. ObserveForever only takes one Observer, and internally wraps the Observer as AlwaysActiveObserver. AlwaysActiveObserver overwrites that shouleBeActive always returns True, but if the active state is not set to true, it still cannot receive data, which is what the last line of observeForever does
C. When adding an observer, if the observer has already been added and the observer is of LifecycleBoundObserver type, and the observer is listening for a different lifecycle than the previous observer, an exception will be thrown, that is, the same observer cannot be used to sense different lifecycle holders
3. Livadata removes both Observer scenarios
// Remove an Observer from the map and disconnect the Observer from the lifecycle holder, setting the state inactive
    @MainThread
    public void removeObserver(@NonNull final Observer<? super T> observer) {
        assertMainThread("removeObserver");
        ObserverWrapper removed = mObservers.remove(observer);
        if (removed == null) {
            return;
        }
        removed.detachObserver();
        removed.activeStateChanged(false);
    }
    
    // Remove all observers bound to this Observer, if more than one is added
    @MainThread
    public void removeObservers(@NonNull final LifecycleOwner owner) {
        assertMainThread("removeObservers");
        for (Map.Entry<Observer<? super T>, ObserverWrapper> entry : mObservers) {
            if(entry.getValue().isAttachedTo(owner)) { removeObserver(entry.getKey()); }}}Copy the code
There are two options for deleting the Observer
The a.emoveObserver is removed from the map and unbound from the lifecycle holder and becomes inactive, triggering an active count change
B. observers are introduced to life cycle holders, and all observers are iterated over, removing all observers bound to the current life cycle holder
4. Two schemes for LiveData to trigger data changes
 // Assign the value of mPendingData to newValue, set mPendingData to its initial value, and notify the Observer to update the data via setValue
    private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run(a) {
            Object newValue;
            synchronized(mDataLock) { newValue = mPendingData; mPendingData = NOT_SET; } setValue((T) newValue); }};// Set a value that will be assigned to mPendingData and then posted to the main thread, which will call setValue, which can be initiated by a child thread
    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if(! postTask) {return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

    // Set a value that is immediately synchronized to the active observer and must be called on the main thread
    @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }


Copy the code
A. PostValue stores the data in mPendingData and changes it to the main thread via postToMainThread. The main thread executes mPostValueRunnable and calls the setValue method to trigger data distribution. This method can be used on child threads
B. setValue is used in the main thread to trigger data update, which is to change the data version number to +1 and then trigger distribution to all observers (active observers).
C. PostValue will determine whether mPendingData is NO_SET. If it is not NO_SET, only mPendingData will be changed. PostToMainThread will not be triggered, which will cause data loss. MPendingData = NOT_SET has two times, one is the initial state, one is called postToMainThread, that is, before the execution of mPostValueRunnable, if the postValue is triggered, Only the value of mPendingData is changed. When mPostValueRunnable is executed, the last value set is synchronized, and the data in the middle is lost
5. Data distribution of LiveData

PostValue and setValue trigger dispatchingValue(NULL); Let’s look at the implementation of dispatchingValue

 // Distribute data to a single Observer
    private void considerNotify(ObserverWrapper observer) {
        // If the observer is not active, it is not distributed
        if(! observer.mActive) {return;
        }
        // If the Observer does not become active, change the Observer state to inactive
        if(! observer.shouldBeActive()) { observer.activeStateChanged(false);
            return;
        }
        // If the version number of the Observer is greater than the version number of the current data, it is not distributed
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        // Synchronize the current version of the data to the observer and distribute the data
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }
    // Whether the input parameter is null determines whether to send data to a single observer or to all observers
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        // If data is being distributed, the distribution is illegal
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        // The distribution is legal
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            // If the incoming observer is not empty, update the data to the incoming observer
            if(initiator ! =null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                // If the incoming observer is empty, the list of observers is iterated to update the data
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break; }}}}while (mDispatchInvalidated);
        mDispatchingValue = false;
    }
Copy the code
The logic of a. considernotify is to send data to a single observer, determine whether the observer is active, whether the observer should be active, the observer data version number and the current data version number, and then synchronize the data version number and trigger onChanged
B. DespatchingValue Determines whether to distribute to a single Observer or multiple observers based on whether the incoming Observer is empty
C. Dispatch validated existence is also a little tricky here; The system adds data that is being distributed and triggers data changes. When the distribution process determines that the MDispatch VALIDATED is true and there is new data, the “while” command is executed to determine that the MDispatch VALIDATED is true to enter a new round of distribution. That is, at the moment of breaking out of the inner loop, the previous observer receives both the original data and the new data, while the subsequent observer receives only the new data and no old data
6. The number of active LiveData observers changes
   // The number of active observers changes
    @MainThread
    void changeActiveCounter(int change) {
        int previousActiveCount = mActiveCount;
        mActiveCount += change;
        // Returns if changes are being made
        if (mChangingActiveState) {
            return;
        }
        mChangingActiveState = true;
        try {
            // The loop is used here because it is returned when the above is changing, but the value of mActiveCount has changed in case it cannot be handled
            while(previousActiveCount ! = mActiveCount) {boolean needToCallActive = previousActiveCount == 0 && mActiveCount > 0;
                boolean needToCallInactive = previousActiveCount > 0 && mActiveCount == 0;
                previousActiveCount = mActiveCount;
                if (needToCallActive) {
                    onActive();
                } else if(needToCallInactive) { onInactive(); }}}finally {
            mChangingActiveState = false; }}Copy the code
A. This logic is triggered when adding a permanently active observer/or when the observer life cycle changes/removes the observer
B. Use circular judgment because if the quantity is changing, another change can be processed until the final quantity is the same; Because mactivevent recounts changes if triggered too frequently, returning if mChangingActiveState is true while changing
C. OnInactive is triggered when the active number changes from >0 to 0, and onActive is triggered when the active number changes from 0 to >0
D. Run the finally command to ensure that mChangingActiveState is false
7. Other code for LiveData
public abstract class LiveData<T> {
    // Used for Sychronized locking
    final Object mDataLock = new Object();
    // Start version
    static final int START_VERSION = -1;
    / / initial value
    static final Object NOT_SET = new Object();
    // Observer and encapsulated observer mapping
    private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
            new SafeIterableMap<>();
    // The active observer
    int mActiveCount = 0;
    // Whether the observer is switching active
    private boolean mChangingActiveState;
    / / data
    private volatile Object mData;
    // The initial value of the next data to change = NOT_SET
    volatile Object mPendingData = NOT_SET;
    // Data version
    private int mVersion;
    // Whether data is being distributed
    private boolean mDispatchingValue;
    // Whether the distribution is legal
    private boolean mDispatchInvalidated;
   

    // If the constructor has an initial value passed in, it is assigned, and the initial value of the version is 0
    public LiveData(T value) {
        mData = value;
        mVersion = START_VERSION + 1;
    }

    // The constructor has no initial value passed in. The default value is NOT_SET and the version number is -1
    public LiveData(a) {
        mData = NOT_SET;
        mVersion = START_VERSION;
    }

    // Returns the current value if NOT_SET, null
    @Nullable
    public T getValue(a) {
        Object data = mData;
        if(data ! = NOT_SET) {return (T) data;
        }
        return null;
    }
    // Get the current version number
    int getVersion(a) {
        return mVersion;
    }

    // Triggered when the number of active observers changes from 0 to 1
    protected void onActive(a) {}// Triggered when the number of active observers changes from 1 to 0
    protected void onInactive(a) {}// Whether there are bound observers
    @SuppressWarnings("WeakerAccess")
    public boolean hasObservers(a) {
        return mObservers.size() > 0;
    }

    // Whether there are active observers for binding
    @SuppressWarnings("WeakerAccess")
    public boolean hasActiveObservers(a) {
        return mActiveCount > 0;
    }
 
    // Check if it is the main thread
    static void assertMainThread(String methodName) {
        if(! ArchTaskExecutor.getInstance().isMainThread()) {throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
                    + " thread"); }}}Copy the code

MutableLiveData and Observer

public class MutableLiveData<T> extends LiveData<T> {

    /**
     * Creates a MutableLiveData initialized with the given {@code value}.
     *
     * @param value initial value
     */
    public MutableLiveData(T value) {
        super(value);
    }

    /** * Creates a MutableLiveData with no value assigned to it. */
    public MutableLiveData(a) {
        super(a); }@Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value); }}Copy the code
public interface Observer<T> {
    /**
     * Called when the data is changed.
     * @param t  The new data
     */
    void onChanged(T t);
}
Copy the code
A. LiveData is an abstract class, and MutableLiveData is the implementation of LiveData. Without any new logic, all methods of LiveData are called
B. Observer is an interface class and does not have the ability to sense the life cycle itself. It has the ability to sense the life cycle only after OberverWapper packaging

Third, summary

1.ObserverWrapper wraps the observer, active status, data version number, lifecycle management, etc
ObserverWrapper implements 1 AlwaysActiveObserver which returns true by overwriting shouldBeActivte to keep itself always active
ObserverWrapper implementation 2 LifecycleBoundObserver, LifecycleBoundObserver by implementing the LifecycleEventObserver interface, As LifeCycleOwner is passed in, LifecycleBoundObserver is added to the observer of LifeCycleOwner for sensing life cycle changes, changing the current active state according to life cycle changes, and monitoring value changes
4. There are two ways to add Observer: One is to pass observe to LifeCycleOwner and Observer, which will be packaged as LifecycleEventObserver; One is through observeForever, which wraps the Observer as AlwaysActiveObserver. You cannot add the same Observer repeatedly for different life cycles
There are two ways to remove an Observer: one is to removeObserver the Observer to be removed from the Map and lifeCycleOwner with the active state set to false. One is that removeObservers, passing LifecycleOwner, determine whether observers in the current list are bound to LifecycleOwner, and call the first method to remove them
6. There are also two ways of data update: one is setValue, which is called by the main thread and immediately notifying the active observer of data update; One is postValue, which can be used on child threads, post to the main thread by handler, and then call setValue, which causes data loss.
7. DispatchingValue has an input parameter Observer that determines whether to send data to this Observer alone or to all observers
Send data to a single Observer: The Observer sends data to a single Observer when it changes from inactive to active
Setvalue calls dispatchingValue and passes in null, sending data to all active observers
8. Restriction on sending data: There are active observers and the data version of the observer is smaller than the current data version. The default data version is -1 or 0, and the default observer data version is -1
9. Observer status changes trigger mActiveCount change
(1). The life cycle holder state of the binding changes
(2). Add/delete Observer
10. ChangeActiveCounter triggers two changes, onActive when the active observer goes from 0 to >0, and onInActive when the active observer goes from >0 to 0
11. Two cases of data loss caused by LiveData
(1) postValue calls postValue again before the last value is distributed
(2) When dispachingValue is called to distribute data A and B, some observers can only receive B