This is the 17th day of my participation in the More text Challenge. For more details, see more text Challenge

Attached is a Livedata usage article

Livedata use paper

Sequence diagram

Not very good at drawing, barely draw a picture

If you have any knowledge of the Livedata source code, this should be enough.

If you don’t know much about the Livedata source code, take a cursory look at the diagram below and look directly at the logic behind it. It’s even better to go back to the logic and look at the sequence diagram

A brief description of the Livedata method invocation

Since it is source code parsing, the natural entrance is our method call, here simply registered Livedata data listening and liveData.setValue method for a simple explanation

Register listen code

MapViewModel. MapLiveData. Observe (this, {/ / in this callback will receive the data changes to monitor logEE (it) tv_map. Text = it})Copy the code

Data change, send data

Val userLivedata =MutableLiveData<User>() fun sendData() {userLiveData. value=User(" liba ",1200)}Copy the code

The next section is a simple analysis of the Livedata workflow

Livedata code logic

I have divided the code logic into three main parts:

  1. Business code liveData. observe Registration data

  2. SetValue Sends the latest data

  3. The user view goes back to the foreground and automatically distributes data

Part I Logic:

The basic logic is that when we register data for listening, a data listener interface will be passed in to LifeCycle. The Observe method of Livedata wraps the interface as a LifecycleBoundObserver object and registers LifeCycle’s listening.

Part II Logic:

When we call the LiveData.setValue method, we walk through each registered LifecycleBoundObserver one by one, and then call the Observer’s onChange callback method separately to return data to our business data listener

Part III Logic:

Because we registered for LifeCycle, the onStateChanged method of LifecycleBoundObserver is called back when the user view goes back to the foreground. Data distribution takes place within the onStateChanged method

This section covers the basic logic of Livedata. The next section will focus on the code

Explain the logic with the code

Register Livedata listening

  1. Observe method body
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) { assertMainThread("observe"); If (owner.getLifecycle().getCurrentState() == DESTROYED) {// If the lifecycle has been DESTROYED, return. // Ignore return; } LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer); ObserverWrapper Existing = mobsers.putifAbsent (observer, wrapper); // This object is an implementation of LifecycleEventObserver and is the observer we register for the lifecycle component. // Insert the wrapper into the map to get the previous wrapper, if (existing! = null && ! Existing isAttachedTo (the owner)) {/ / isAttachedTo: If the lifecycle associated with the last wrapper is not the current lifecycle, Throw new IllegalArgumentException("Cannot add the same observer" + "with different lifecycles"); } if (existing ! = null) {return if the previous wrapper is not empty (because it will reuse the previous wrapper) return; } owner.getLifecycle().addObserver(wrapper); // If the previous one is null, it is the first time, and you need to register the lifecycle listener}Copy the code

Livedata.setValue

  1. First look at the setValue method body:
protected void setValue(T value) { assertMainThread("setValue"); mVersion++; // The version of the data, each call to setValue ++ mData = value; dispatchingValue(null); // Distribute data}Copy the code
  1. We noticed that the dispatchingValue method was called at the end, so take a look at the body of the dispatchingValue method again
Void dispatchingValue(@nullable ObserverWrapper Initiator) {if (mDispatchingValue) {// 1 mDispatchInvalidated = true; // 2. If a new setValue method is called, it will break out of the for loop in Step 4 and issue a return again. } mDispatchingValue = true; Do {mDispatchInvalidated = false; // 3. Set the status of dispatching to true to prevent duplicate messages in 1. // 4. After the loop is entered, set the value of mDispatchInvalidated to False. If the value of mDispatchInvalidated needs to be validated, set the value of mDispatchInvalidated to true. If (initiator! = null) { considerNotify(initiator); // 5. Distribute messages initiator = null; } else { for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator = mObservers.iteratorWithAdditions(); iterator.hasNext(); ) { considerNotify(iterator.next().getValue()); If (mDispatchInvalidated) {//6. If (mDispatchInvalidated) {//6. If (mDispatchInvalidated) {//6. } } } } while (mDispatchInvalidated); mDispatchingValue = false; //7. Set the status of the message being distributed to false}Copy the code

3. Through analysis, we find that the method of dispatchingValue finally distributes the message again is considerNotify, the method body:

private void considerNotify(ObserverWrapper observer) { if (! Observer.mactive) {//1, if the current lifecycle is not active then no message will be distributed. Destruction will be automatically distributed at the last active time in the lifecycle return; } if (! Observer. ShouldBeActive ()) {/ / 2, if the lifecycle status to started | | resumed the observer. The activeStateChanged (false); //3, active, activeStateChanged method will call dispatchValue again to send the message, usually used to automatically send the message return when liveData from inactive to active; } if (observer.mlastversion >= mVersion) {if (observer.mlastversion >= mVersion) {if (observer.mlastversion >= mVersion); } observer.mLastVersion = mVersion; / / 5, remember that current version is distributing the value, used in the fourth in logic observer. MObserver. OnChanged (mData (T)); //6, call the onChanged observer registered with LiveData to notify users to update data}Copy the code

By calling mobServer. onChanged in the notify method, we call back to our business code to register the listener, and the logic of the data flow is complete

The view comes back to the foreground

Logic with Livedata. SetValue

We know that we listen to the LifeCycle through the LifeCycle component.

The interface implementation for listening to the lifecycle is the LifecycleBoundObserver class, which calls back to the method onStateChanged of the LifecycleBoundObserver class when the lifecycle changes:

  1. The onStateChanged method body is as follows
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) { Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState(); If (currentState == DESTROYED) {remove removeObserver(mObserver) from the window if (currentState == DESTROYED); return; } Lifecycle.State prevState = null; while (prevState ! = currentState) {prevState = currentState; prevState = currentState; activeStateChanged(shouldBeActive()); CurrentState = mowner.getLifecycle ().getCurrentState(); // Reset the lifecycle state}}Copy the code
  1. ActiveStateChanged method body
void activeStateChanged(boolean newActive) { if (newActive == mActive) { return; } mActive = newActive; changeActiveCounter(mActive ? 1:1); if (mActive) { dispatchingValue(this); // If you see this, you can directly go to the source analysis of liveData.setValue in the previous section.Copy the code

postValue

There really isn’t much to say, just cut the thread back to the main thread and call liveData.setValue to update the data.

Finally, and more importantly here:

Follow my official account “Ananzhuo” to learn more