Method of use

LiveData can be thought of as an observer pattern implementation with a lifecycle added. Let’s look at a usage example

private val data = MutableLiveData<User>()

data.observe(lifecycleOwner) {
    // TODO
}

// Send data
data.value = User()
// Send data asynchronously
data.postValue(User())
Copy the code

Source code analysis

consumers

From observe, look at the Observe method in the LiveData class

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    // Can only listen on the main thread
    assertMainThread("observe");
    If Lifecycle has been destroyed, return without listening
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        // ignore
        return;
    }
    // Wrap LifecycleOwner and Observer
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    // Add an Observer to the HashMap
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    if(existing ! =null && !existing.isAttachedTo(owner)) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    // If the same Observer already exists, return it
    if(existing ! =null) {
        return;
    }
    // Add an Observer to Lifecycle
    owner.getLifecycle().addObserver(wrapper);
}
Copy the code

LifecycleBoundObserver must inherit from LifecycleObserver

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
    @NonNull
    final LifecycleOwner mOwner;

    LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
        super(observer);
        mOwner = owner;
    }

    @Override
    boolean shouldBeActive(a) {
        // Key code to ensure that the Activity is active when the observer receives a value
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }

    @Override
    public void onStateChanged(@NonNull LifecycleOwner source,
            @NonNull Lifecycle.Event event) {
        Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
        // Lifecycle is destroyed, indicating that the Activity is destroyed
        if (currentState == DESTROYED) {
            // Remove the listener
            removeObserver(mObserver);
            return;
        }
        Lifecycle.State prevState = null;
        while(prevState ! = currentState) { prevState = currentState;// Distribute values when the state changesactiveStateChanged(shouldBeActive()); currentState = mOwner.getLifecycle().getCurrentState(); }}@Override
    boolean isAttachedTo(LifecycleOwner owner) {
        return mOwner == owner;
    }

    @Override
    void detachObserver(a) {
        mOwner.getLifecycle().removeObserver(this);
    }
Copy the code

LifecycleEventObserver implementation

public interface LifecycleEventObserver extends LifecycleObserver {
    void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event);
}
Copy the code

LifecycleBoundObserver inherits the ObserverWrapper, implements the LifecycleEventObserver interface, and stores the LifecycleOwner and Observer. One of the key lines of code is

mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED)
Copy the code

Used to ensure that the consumer always receives a value while the Activity is active.

Now what does the ObserverWrapper class do

private abstract class ObserverWrapper {
    final Observer<? super T> mObserver;
    boolean mActive;
    int mLastVersion = START_VERSION;

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

    abstract boolean shouldBeActive(a);

    boolean isAttachedTo(LifecycleOwner owner) {
        return false;
    }

    void detachObserver(a) {}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) {
            / / distribution
            dispatchingValue(this); }}}Copy the code

The general function is to call dispatchingValue to distribute the value when the state changes, so the consumer analysis ends there and then analyzes what is done after the LiveData value is set

producers

  • synchronously
@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    // Version+1
    mVersion++;
    mData = value;
    dispatchingValue(null);
}
Copy the code

The code is very simple, it’s just a matter of setting the value, calling dispatchingValue and distributing the value, and saying dispatchingValue does what

void dispatchingValue(@Nullable ObserverWrapper initiator) {
    // Whether the value is currently being distributed, if so, returns directly
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        // First distribution
        if(initiator ! =null) {
            considerNotify(initiator);
            initiator = null;
        } else {
            / / traverse the Observer
            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

You can see the actual distributed values in considerNotify, and then scroll through the considerNotify method

private void considerNotify(ObserverWrapper observer) {
    // Determine whether the current state can distribute values
    if(! observer.mActive) {return;
    }
    
    if(! observer.shouldBeActive()) { observer.activeStateChanged(false);
        return;
    }
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    observer.mObserver.onChanged((T) mData);
}
Copy the code

The code is as simple as taking the Observer out of ObserverWrapper and calling its onChanged method to distribute the value.

What about sending values asynchronously

  • asynchronous

PostValue method

protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if(! postTask) {return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
Copy the code

Post an mPostValueRunnable to the main thread using ArchTaskExecutor, so look at the mPostValueRunnable content

private final Runnable mPostValueRunnable = new Runnable() {
    @SuppressWarnings("unchecked")
    @Override
    public void run(a) {
        Object newValue;
        synchronized(mDataLock) { newValue = mPendingData; mPendingData = NOT_SET; } setValue((T) newValue); }};Copy the code

MPostValueRunnable fetched the value from mPendingData and then called the synchronous setValue method. At this point, the implementation principle of LiveData is basically finished, the code is relatively simple, the source code is only a file.