Series of articles look here

Android Jetpack Architecture Components — What is Jetpack?

Android Jetpack architecture component — Lifecycle usage

Android Jetpack Architecture component — Lifecycle Principles

Android Jetpack Architecture Components – This article takes you through the ViewModel and how it works

Android Jetpack architecture component – LiveData Usage

Android Jetpack Architecture component – LiveData Principles

An overview of the

Earlier we talked about how lifecycle is used, but it is not enough that we know how to use it, we need to know exactly how lifecycle is bound. So in this part we will look at the principles of Lifecycle.

This article is based on Android 9.0 source code analysis, if there is a difference, pay attention to the SDK version.

Lifecycle is what?

Lifecycle is a class that stores the Lifecycle state of a component, such as an Activity or Fragment. And allow other components to observe these states.

Let’s take a quick look at the source code for Lifecycle:

public abstract class Lifecycle { @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) @NonNull AtomicReference<Object> mInternalScopeRef = new AtomicReference<>(); @MainThread public abstract void addObserver(@NonNull LifecycleObserver observer); @MainThread public abstract void removeObserver(@NonNull LifecycleObserver observer); @MainThread @NonNull public abstract State getCurrentState(); @SuppressWarnings("WeakerAccess") public enum Event { ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY, ON_ANY } @SuppressWarnings("WeakerAccess") public enum State { DESTROYED, INITIALIZED, CREATED, STARTED, RESUMED; public boolean isAtLeast(@NonNull State state) { return compareTo(state) >= 0; }}}Copy the code

Lifecycle is defined as two enumerations. One is an Event that represents the Lifecycle events allocated by Lifecycle and maps to the Lifecycle callback events of an activity or fragment. There is also State, which means the Lifecycle State that Lifecycle is in. The following figure shows the relationship between State and Event.

How to associate with activities and Fragments?

We know that generally our activity inherits from FragmentActivity. So FragmentActivity inherits from ComponentActivity. ComponentActivity (ComponentActivity)

@RestrictTo(LIBRARY_GROUP_PREFIX) public class ComponentActivity extends Activity implements LifecycleOwner, KeyEventDispatcher.Component { @SuppressWarnings("deprecation") private SimpleArrayMap<Class<? extends ExtraData>, ExtraData> mExtraDataMap = new SimpleArrayMap<>(); private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this); @SuppressWarnings("deprecation") @RestrictTo(LIBRARY_GROUP_PREFIX) @Deprecated public void putExtraData(ExtraData extraData) { mExtraDataMap.put(extraData.getClass(), extraData); } @SuppressLint("RestrictedApi") @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); ReportFragment.injectIfNeededIn(this); } @CallSuper @Override protected void onSaveInstanceState(@NonNull Bundle outState) { mLifecycleRegistry.markState(Lifecycle.State.CREATED); super.onSaveInstanceState(outState); } @RestrictTo(LIBRARY_GROUP_PREFIX) @SuppressWarnings({"unchecked", "deprecation"}) @Deprecated public <T extends ExtraData> T getExtraData(Class<T> extraDataClass) { return (T) mExtraDataMap.get(extraDataClass); } @NonNull @Override public Lifecycle getLifecycle() { return mLifecycleRegistry; }... }Copy the code

We can see that ComponentActivity implements the LifecycleOwner interface. LifecycleRegistry is also defined. LifecycleRegistry is an implementation class for Lifecycle. We will not look at the specific logic, are interested in their own attention.

In the code above we can see that in the onSaveInstanceState method we set the State to Lifecycle.state.created using makeState. So why can’t you find the logic to set the other states? We can see that there is an Inject method in the onCreate method. We go into this method and, alas, it finds it. Let’s take a look at its source code:

. static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) { if (activity instanceof LifecycleRegistryOwner) { ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event); return; } if (activity instanceof LifecycleOwner) { Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle(); if (lifecycle instanceof LifecycleRegistry) { ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event); } } } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); dispatchCreate(mProcessListener); dispatch(Lifecycle.Event.ON_CREATE); } @Override public void onStart() { super.onStart(); dispatchStart(mProcessListener); dispatch(Lifecycle.Event.ON_START); } @Override public void onResume() { super.onResume(); dispatchResume(mProcessListener); dispatch(Lifecycle.Event.ON_RESUME); } @Override public void onPause() { super.onPause(); dispatch(Lifecycle.Event.ON_PAUSE); } @Override public void onStop() { super.onStop(); dispatch(Lifecycle.Event.ON_STOP); } @Override public void onDestroy() { super.onDestroy(); dispatch(Lifecycle.Event.ON_DESTROY); // just want to be sure that we won't leak reference to an activity mProcessListener = null; } private void dispatch(@NonNull Lifecycle.Event event) { if (Build.VERSION.SDK_INT < 29) { // Only dispatch events from  ReportFragment on API levels prior // to API 29. On API 29+, this is handled by the ActivityLifecycleCallbacks // added in ReportFragment.injectIfNeededIn dispatch(getActivity(), event); }}...Copy the code

We can see that the Dispatch method is called during the corresponding lifecycle, and a multi-parameter Dispatch method is called within the Dispatch method. This method determines whether the activity belongs to LifecycleRegistryOwner or LifecycleRegistry. This will all end up in the handleLifecycleEvent method of LifecycleRegistry.

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) { State next = getStateAfter(event); moveToState(next); } private void moveToState(State next) { if (mState == next) { return; } mState = next; if (mHandlingEvent || mAddingObserverCounter ! = 0) { mNewEventOccurred = true; // we will figure out what to do on upper level. return; } mHandlingEvent = true; sync(); mHandlingEvent = false; } static State getStateAfter(Event event) { switch (event) { case ON_CREATE: case ON_STOP: return CREATED; case ON_START: case ON_PAUSE: return STARTED; case ON_RESUME: return RESUMED; case ON_DESTROY: return DESTROYED; case ON_ANY: break; } throw new IllegalArgumentException("Unexpected event value " + event); }Copy the code

We can see that it uses getStateAfter to get the state of the event, as shown in the sequence diagram above. In the moveToState method it calls sync again:

private void sync() { LifecycleOwner lifecycleOwner = mLifecycleOwner.get(); if (lifecycleOwner == null) { throw new IllegalStateException("LifecycleOwner of this LifecycleRegistry is already" + "garbage collected. It is too late to change lifecycle state."); } while (! isSynced()) { mNewEventOccurred = false; // no need to check eldest for nullability, because isSynced does it for us. if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) { backwardPass(lifecycleOwner); } Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest(); if (! mNewEventOccurred && newest ! = null && mState.compareTo(newest.getValue().mState) > 0) { forwardPass(lifecycleOwner); } } mNewEventOccurred = false; }Copy the code

Here it will be compared with the states that newest gets from mObserverMap’s eldest and eldest to determine whether it’s forward or backward. For example, ON_CREATE=>ON_START is forward, and ON_START=>ON_CREATE is backward. The overall process is similar. Here is a code example:

private void forwardPass(LifecycleOwner lifecycleOwner) { Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator = mObserverMap.iteratorWithAdditions(); while (ascendingIterator.hasNext() && ! mNewEventOccurred) { Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next(); ObserverWithState observer = entry.getValue(); while ((observer.mState.compareTo(mState) < 0 && ! mNewEventOccurred && mObserverMap.contains(entry.getKey()))) { pushParentState(observer.mState); observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState)); popParentState(); } } } private void backwardPass(LifecycleOwner lifecycleOwner) { Iterator<Entry<LifecycleObserver, ObserverWithState>> descendingIterator = mObserverMap.descendingIterator(); while (descendingIterator.hasNext() && ! mNewEventOccurred) { Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next(); ObserverWithState observer = entry.getValue(); while ((observer.mState.compareTo(mState) > 0 && ! mNewEventOccurred && mObserverMap.contains(entry.getKey()))) { Event event = downEvent(observer.mState); pushParentState(getStateAfter(event)); observer.dispatchEvent(lifecycleOwner, event); popParentState(); }}}Copy the code

Eventually it will go observer.dispatchEvent(lifecycleOwner, event); Methods. And will eventually call mLifecycleObserver. OnStateChanged (the owner, the event); That’s how Life Dinner Server works. We see LifecycleEventObserver based implementation class ReflectiveGenericLifecycleObserver.

class ReflectiveGenericLifecycleObserver implements LifecycleEventObserver { private final Object mWrapped; private final CallbackInfo mInfo; ReflectiveGenericLifecycleObserver(Object wrapped) { mWrapped = wrapped; mInfo = ClassesInfoCache.sInstance.getInfo(mWrapped.getClass()); } @Override public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Event event) { mInfo.invokeCallbacks(source, event, mWrapped); }}Copy the code

The invokeCallbacks method of CallbackInfo is called in onStateChanged:

void invokeCallbacks(LifecycleOwner source, Lifecycle.Event event, Object target) { invokeMethodsForEvent(mEventToHandlers.get(event), source, event, target); invokeMethodsForEvent(mEventToHandlers.get(Lifecycle.Event.ON_ANY), source, event, target); } private static void invokeMethodsForEvent(List<MethodReference> handlers, LifecycleOwner source, Lifecycle.Event event, Object mWrapped) { if (handlers ! = null) { for (int i = handlers.size() - 1; i >= 0; i--) { handlers.get(i).invokeCallback(source, event, mWrapped); } } } static class MethodReference { final int mCallType; final Method mMethod; MethodReference(int callType, Method method) { mCallType = callType; mMethod = method; mMethod.setAccessible(true); } void invokeCallback(LifecycleOwner source, Lifecycle.Event event, Object target) { //noinspection TryWithIdenticalCatches try { switch (mCallType) { case CALL_TYPE_NO_ARG: mMethod.invoke(target); break; case CALL_TYPE_PROVIDER: mMethod.invoke(target, source); break; case CALL_TYPE_PROVIDER_WITH_EVENT: mMethod.invoke(target, source, event); break; } } catch (InvocationTargetException e) { throw new RuntimeException("Failed to call observer method", e.getCause()); } catch (IllegalAccessException e) { throw new RuntimeException(e); }}... }...Copy the code

The invokeCallback Method of MethodReference has two variables: callType (Method) and Method (Method). Either callType reflects the method via invoke.

conclusion

Finally, we conclude the process with a sequence diagram of the invocation.

reference

The official documentation

This article was first published on my personal blog: Android Jetpack Architectural Components — Lifecycle Principles

For more articles, please pay attention to my official number:Code the farmers work