Previous Hard core explains the use of life cycle of Jetpack This paper mainly introduces the significance of life cycle, basic and advanced use methods. Today, I don't want to talk much about it, just start rolling source code.
This article is based on the android_9.0.0_r45 Source code, all relevant source code including comments have been uploaded to my Github, you can directly clone down to check the article.
LifeCycle three swordsmen
Before reading the source code, it is necessary to introduce several terms, Lifecycle owner, Lifecycle observer and Lifecycle.
Lifecycle owner is an interface, which is usually used to declare a certain capability. The ability of lifecycle owner is to have a lifecycle. Typical lifecycle components are Activity and Fragment. Of course, we can also customize lifecycle components. Lifecycle owner provides the getLifecycle() method to get its lifecycle object.
public interface LifecycleOwner { @NonNull Lifecycle getLifecycle(); }
Lifecycle observer is a lifecycle observer, which is an empty interface. It does not have any methods and relies on the onlifcycleevent annotation to receive lifecycle callbacks.
public interface LifecycleObserver { }
Life cycle components and life cycle observers all have them, and life cycle is the bridge between them.
Lifecycle is a specific lifecycle object. Each lifecycle owner will hold lifecycle. Through lifecycle, we can get the current lifecycle state, add / remove lifecycle observers and so on.
Two enumeration classes, event and State, are defined inside Lifecycle. Event represents a Lifecycle event, which corresponds to the Lifecycle event of Lifecycle owner.
public enum Event { /** * Constant for onCreate event of the {@link LifecycleOwner}. */ ON_CREATE, /** * Constant for onStart event of the {@link LifecycleOwner}. */ ON_START, /** * Constant for onResume event of the {@link LifecycleOwner}. */ ON_RESUME, /** * Constant for onPause event of the {@link LifecycleOwner}. */ ON_PAUSE, /** * Constant for onStop event of the {@link LifecycleOwner}. */ ON_STOP, /** * Constant for onDestroy event of the {@link LifecycleOwner}. */ ON_DESTROY, /** * An {@link Event Event} constant that can be used to match all events. */ ON_ANY }
On any is special. It represents any life cycle event. Why design on any? In fact, I don't know. I haven't found its use yet.
Another enumeration class, State, represents the lifecycle State.
public enum State { /** * After that, Lifecycle no longer dispatches Lifecycle events. * This state is before Activity.onDestroy() */ DESTROYED, /** * Before Activity has been instantiated but not onCreate() */ INITIALIZED, /** * After onCreate() of Activity and before onStop() */ CREATED, /** * After onStart() of Activity and before onPause() */ STARTED, /** * After onResume() of Activity */ RESUMED; public boolean isAtLeast(@NonNull State state) { return compareTo(state) >= 0; } }
State s can be relatively difficult to understand, especially the order of enumeration values. We will not explain it in detail here, but we must remember the order of these enumeration values, specified - INITIALIZED - CREATED - STARTED - RESUMED, which is particularly important for the understanding of the source code.
Simply sort out the relationship among the three swordsmen. After the lifecycle component lifecycle owner enters a specific lifecycle, it sends a specific lifecycle Event event to inform Lifcycle to enter a specific State, and then calls back the specified method of lifecycle observer lifecycle observer.
Start with addObserver()
If we can't start with the source code, we will start with the basic use of Lifecycle.
lifecycle.addObserver(LocationUtil( ))
Lifecycle is actually the getLifecycle() method, which is only abbreviated in Kotlin. getLifecycle() is the method of the interface lifecycle owner. AppCompatActivity does not directly implement lifecycle owner, nor does its parent class FragmentActivity. Only in its grandparent class ComponentActivity can we find the trace of lifecycle owner. Let's see the implementation of the interface.
@Override public Lifecycle getLifecycle() { return mLifecycleRegistry; }
Mlifcycleregistry is the LifecycleRegistry object, and LifecycleRegistry is the implementation class of LifeCycle. So the LifeCycle registry here is our LifeCycle object. Take a look at its addObserver() method.
> LifecycleRegistry.java ...... // Save LifecycleObserver and its corresponding State private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap = new FastSafeIterableMap<>(); // Current lifecycle state private State mState; /** * Add lifecycle observer lifecycle observer * In addition, pay attention to the "backflow" of life cycle events. If addObserver() is called in onResume(), * Observers can still receive onCreate and onStart events. * The purpose of this is to ensure that the lifecycle observer in the mbobservermap is always in the same state */ @Override public void addObserver(@NonNull LifecycleObserver observer) { State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED; // ObserverWithState is a static inner class ObserverWithState statefulObserver = new ObserverWithState(observer, initialState); ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver); if (previous != null) { return; } LifecycleOwner lifecycleOwner = mLifecycleOwner.get(); if (lifecycleOwner == null) { // it is null we should be destroyed. Fallback quickly return; } // Judge whether to reenter boolean isReentrance = mAddingObserverCounter != 0 || mHandlinengEvent; State targetState = calculateTargetState(observer); mAddingObserverCounter++; // Synchronize to targetState if the observer's initial state is less than targetState while ((statefulObserver.mState.compareTo(targetState) < 0 && mObserverMap.contains(observer))) { pushParentState(statefulObserver.mState); statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState)); popParentState(); // mState / subling may have been changed recalculate targetState = calculateTargetState(observer); } if (!isReentrance) { // we do sync only on the top level. sync(); } mAddingObserverCounter--; }
There are two problems to pay attention to. The first problem is the "backflow problem" of the life cycle. This is a word I borrowed from LiveData. What is the specific problem? For example, even if you call the addObserver() method in onResume() to add an observer, the observer can receive onCreate and onStart events in turn, and finally synchronize to targetState. The targetState is calculated by the calculateTargetState(observer) method.
/** * The calculated targetState must be less than or equal to the current mState */ private State calculateTargetState(LifecycleObserver observer) { // Get the previous Observer of the current Observer Entry<LifecycleObserver, ObserverWithState> previous = mObserverMap.ceil(observer); State siblingState = previous != null ? previous.getValue().mState : null; // parentState can be ignored without reentry, null State parentState = !mParentStates.isEmpty() ? mParentStates.get(mParentStates.size() - 1) : null; return min(min(mState, siblingState), parentState); }
We can add multiple lifecycle observers, so we need to pay attention to maintaining their state. Each time a new observer is added, its initial state is INITIALIZED, and it needs to be synchronized to the current life cycle state. Specifically, it needs to be synchronized to a targetState no larger than the current state. The calculation method in the source code also reflects that targetState is the minimum of the current state mState, the last observer state in the mbobservermap, and the parentState state in the case of reentry.
Why take this minimum? I understand that when there is a new life cycle event, all observers in the mbobservermap need to be synchronized to the new same state. This synchronization process may not be completed, so the newly added observers can only synchronize to the minimum state first. Note that in the while loop of the addObserver method, the new observer will call calculateTargetState() to recalculate the targetState every time he changes the life cycle.
In the final stable state, there is no lifecycle switch, no new observers are added, and all observers in the mbobservermap should be in the same lifecycle state.
Who will distribute lifecycle events?
Observers have been added, so how to inform observers of changes in the lifecycle?
Go back to ComponentActivity and you'll see that it doesn't override all life cycle functions. The only suspicious line is one in onCreate().
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mSavedStateRegistryController.performRestore(savedInstanceState); ReportFragment.injectIfNeededIn(this); if (mContentLayoutId != 0) { setContentView(mContentLayoutId); } }
The report fragment here is the answer. Catch the injectifneedin() method.
public static void injectIfNeededIn(Activity activity) { // Compatible with android.app.FragmentManager android.app.FragmentManager manager = activity.getFragmentManager(); if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) { manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit(); // Hopefully, we are the first to make a transaction. manager.executePendingTransactions(); } }
Here a Fragment without page is injected into the Activity. This reminds me that some dynamic permission libraries are the same routine, which can be used to proxy permission requests by injecting Fragment. Unsurprisingly, ReportFragment is where the lifecycle is really distributed.
@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; }
mProcessListener deals with the application process life cycle, and it will not be managed temporarily.
First look at the dispatch() method.
private void dispatch(Lifecycle.Event event) { Activity activity = getActivity(); if (activity instanceof LifecycleRegistryOwner) { ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event); return; } if (activity instanceof LifecycleOwner) { Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle(); if (lifecycle instanceof LifecycleRegistry) { // Call the lifecycleregistry. Handlelifcycleevent() method ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event); } } }
In each life cycle function of ReportFragment, the life cycle events are distributed through the dispatch() method, and then the handlelifcycleevent() method of LifecycleRegistry is called to process. For the convenience of later code understanding, it is assumed that the process of synchronizing from onStart() to onResume() is going on, that is, the parameter in the handlelifcycleevent() method is on ﹐ resume.
// Set the current state and notify the observer public void handleLifecycleEvent(@NonNull Lifecycle.Event event) { State next = getStateAfter(event); moveToState(next); }
The function of getStateAfter() is to get the state after the Event and notify the observer to synchronize to this lifecycle state.
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); }
The parameter is on "resume, so the state to be synchronized to is RESUMED. Next, take a look at the logic of the moveToState() method.
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; }
First, assign the lifecycle state to be synchronized to the current lifecycle state mState, where the value of mState is RESUMED. The sync() method is then called to synchronize the state of all observers.
private void sync() { LifecycleOwner lifecycleOwner = mLifecycleOwner.get(); if (lifecycleOwner == null) { Log.w(LOG_TAG, "LifecycleOwner is garbage collected, you shouldn't try dispatch " + "new events from it."); return; } while (!isSynced()) { mNewEventOccurred = false; // MState is the current state. If mState is less than the state value in mbobservermap, backwardPass() is called if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) { backwardPass(lifecycleOwner); } Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest(); // If mState is greater than the state value in the mbobservermap, call forwardPass() if (!mNewEventOccurred && newest != null && mState.compareTo(newest.getValue().mState) > 0) { forwardPass(lifecycleOwner); } } mNewEventOccurred = false; }
Here, the State values of observers in mState and mbobservermap are compared to determine whether the State needs to be synchronized forward or backward. Now the value of mState is RESUMED, and the observer is still in the previous State STARTED, so the observer's State has to move forward. Here, the forwardPass() method is called.
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(); // Pass the event up until the status value of the observer is equal to the current status value while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred && mObserverMap.contains(entry.getKey()))) { pushParentState(observer.mState); // Distribute lifecycle events observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState)); popParentState(); } } }
forwardPass() synchronizes all observers in the mbobservermap to the specified lifecycle state. If the span is large, the intermediate state will be distributed in turn. Distribution of lifecycle events ultimately depends on the dispatchEvent() method of ObserverWithState.
Here first pause archiving, do not continue to pursue the source code. The scenario assumed above is the process from on start to on resume. Now suppose another scenario, I press the Home key directly to return to the desktop. The current Activity's life cycle is from onResumed to onPaused. The process is as follows.
-
ReportFragment calls dispatch (lifecycle. Event. On pause) to distribute the on pause event
-
Call the lifecycleregistry. Handlelifcycleevent() method with the parameter on "pause"
-
getStateAfter() gets that the state to be synchronized is STARTED, assigns it to mState, and then calls moveToState()
-
Call sync() method in moveToState(Lifecycle.State.STARTED) to synchronize
-
In the sync() method, the value of mState is STARTED, while the state of observers in the mbobservermap is RESUMED. So the observers all need to move a step back, which calls the backwardPass() method.
The backwardPass() method is similar to the forwardPass() method.
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(); // Pass the event down until the status value of the observer is equal to the current status value while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred && mObserverMap.contains(entry.getKey()))) { Event event = downEvent(observer.mState); pushParentState(getStateAfter(event)); // Distribute lifecycle events observer.dispatchEvent(lifecycleOwner, event); popParentState(); } } }
The only difference between the two is to get the events to be distributed, one is upEvent(), the other is downEvent().
upEvent() is the event that needs to be experienced to get the state upgrade, and downEvent() is the event that needs to be experienced to get the state downgrade.
private static Event upEvent(State state) { switch (state) { case INITIALIZED: case DESTROYED: return ON_CREATE; case CREATED: return ON_START; case STARTED: return ON_RESUME; case RESUMED: throw new IllegalArgumentException(); } throw new IllegalArgumentException("Unexpected state value " + state); } private static Event downEvent(State state) { switch (state) { case INITIALIZED: throw new IllegalArgumentException(); case CREATED: return ON_DESTROY; case STARTED: return ON_STOP; case RESUMED: return ON_PAUSE; case DESTROYED: throw new IllegalArgumentException(); } throw new IllegalArgumentException("Unexpected state value " + state); }
Upgrade is required from STARTED to RESUMED. The return value of upEvent(STARTED) is on "resume. From RESUMED to STARTED, degradation is required. The return value of downEvent(RESUMED) is on "pause".
I don't know if you're a little confused. I also groped for a long time about the relationship between State and Event. Do you remember the enumeration value order of States first?
DESTROYED - INITIALIZED - CREATED - STARTED - RESUMED
DESTROYED is the smallest and RESUMED is the largest. The last life cycle event distributed when onResume enters the onPause phase is indeed on pause, but the observer's state is set to STARTED. Why is that?
As for the relationship between State and Event, the official website gives a figure as follows:
But I have to say that the painting is a little abstract, in fact, it should be changed. Another one. I'm here here Here is a picture:
Is there a clear sense of the Event between States, the State after the Event, and the size between States? It's very important to understand this picture. If you can't understand the relationship between Event and State, you can't understand the source code of Lifecycle.
Who will call back your annotation method?
Read the pause archive just now, and the sync() method of synchronizing the Observer life cycle will eventually call the dispatchEvent() method of ObserverWithState.
static class ObserverWithState { State mState; GenericLifecycleObserver mLifecycleObserver; ObserverWithState(LifecycleObserver observer, State initialState) { mLifecycleObserver = Lifecycling.getCallback(observer); mState = initialState; } void dispatchEvent(LifecycleOwner owner, Event event) { State newState = getStateAfter(event); mState = min(mState, newState); // ReflectiveGenericLifecycleObserver.onStateChanged() mLifecycleObserver.onStateChanged(owner, event); mState = newState; } }
Mlifcycleobserver is assigned through the lifecycle. Getcallback() method.
@NonNull static GenericLifecycleObserver getCallback(Object object) { if (object instanceof FullLifecycleObserver) { return new FullLifecycleObserverAdapter((FullLifecycleObserver) object); } if (object instanceof GenericLifecycleObserver) { return (GenericLifecycleObserver) object; } final Class<?> klass = object.getClass(); int type = getObserverConstructorType(klass); // Get type // GENERATED_CALLBACK indicates the code generated by the annotation // Reflective ﹣ callback means to use reflection if (type == GENERATED_CALLBACK) { List<Constructor<? extends GeneratedAdapter>> constructors = sClassToAdapters.get(klass); if (constructors.size() == 1) { GeneratedAdapter generatedAdapter = createGeneratedAdapter( constructors.get(0), object); return new SingleGeneratedAdapterObserver(generatedAdapter); } GeneratedAdapter[] adapters = new GeneratedAdapter[constructors.size()]; for (int i = 0; i < constructors.size(); i++) { adapters[i] = createGeneratedAdapter(constructors.get(i), object); } return new CompositeGeneratedAdaptersObserver(adapters); } return new ReflectiveGenericLifecycleObserver(object); }
If the defaultlifecycle observer is used, and the defaultlifecycle observer inherits the fulllifecycle observer, the fulllifecycle observer adapter will be returned here.
If it's just a normal lifecycle observer, you need to use the getObserverConstructorType() method to determine whether the annotation or reflection is used.
private static int getObserverConstructorType(Class<?> klass) { if (sCallbackCache.containsKey(klass)) { return sCallbackCache.get(klass); } int type = resolveObserverCallbackType(klass); sCallbackCache.put(klass, type); return type; } private static int resolveObserverCallbackType(Class<?> klass) { // anonymous class bug:35073837 // Anonymous inner class uses reflection if (klass.getCanonicalName() == null) { return REFLECTIVE_CALLBACK; } // Find the GeneratedAdapter class generated by the annotation Constructor<? extends GeneratedAdapter> constructor = generatedConstructor(klass); if (constructor != null) { sClassToAdapters.put(klass, Collections .<Constructor<? extends GeneratedAdapter>>singletonList(constructor)); return GENERATED_CALLBACK; } // Find a method annotated by OnLifecycleEvent boolean hasLifecycleMethods = ClassesInfoCache.sInstance.hasLifecycleMethods(klass); if (hasLifecycleMethods) { return REFLECTIVE_CALLBACK; } // The GeneratedAdapter class generated by the annotation was not found, nor was the onlife event annotation found, // Then look up for the parent class Class<?> superclass = klass.getSuperclass(); List<Constructor<? extends GeneratedAdapter>> adapterConstructors = null; if (isLifecycleParent(superclass)) { if (getObserverConstructorType(superclass) == REFLECTIVE_CALLBACK) { return REFLECTIVE_CALLBACK; } adapterConstructors = new ArrayList<>(sClassToAdapters.get(superclass)); } // Look for interface implementation for (Class<?> intrface : klass.getInterfaces()) { if (!isLifecycleParent(intrface)) { continue; } if (getObserverConstructorType(intrface) == REFLECTIVE_CALLBACK) { return REFLECTIVE_CALLBACK; } if (adapterConstructors == null) { adapterConstructors = new ArrayList<>(); } adapterConstructors.addAll(sClassToAdapters.get(intrface)); } if (adapterConstructors != null) { sClassToAdapters.put(klass, adapterConstructors); return GENERATED_CALLBACK; } return REFLECTIVE_CALLBACK; }
Notice the hasLifecycleMethods() method.
boolean hasLifecycleMethods(Class klass) { if (mHasLifecycleMethods.containsKey(klass)) { return mHasLifecycleMethods.get(klass); } Method[] methods = getDeclaredMethods(klass); for (Method method : methods) { OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class); if (annotation != null) { createInfo(klass, methods); return true; } } mHasLifecycleMethods.put(klass, false); return false; }
Look for the OnLifecycleEvent annotation here. So the type of MyObserver we implemented with the OnLifecycleEvent annotation is reflexive ﹣ callback, which means using reflection call. Note that another type, generated'callback, represents code generated using annotations, not reflections.
So, * * LifeCycle can choose to use apt compile time to generate code to avoid using runtime reflection to optimize performance? **It's like that. This reminds me that index acceleration of EventBus is also off by default. See, this is the advantage of reading the source code. You can always find your own knowledge blind spot. Add the following dependencies to speed up LifeCycle!
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
For the convenience of parsing, it is better to return to the reflection call.
What we have defined to call in the normal observer is reflective generic lifecycle observer. Onstatechanged().
class ReflectiveGenericLifecycleObserver implements GenericLifecycleObserver { private final Object mWrapped; // Observer object private final CallbackInfo mInfo; // Reflection getting annotation information ReflectiveGenericLifecycleObserver(Object wrapped) { mWrapped = wrapped; mInfo = ClassesInfoCache.sInstance.getInfo(mWrapped.getClass()); } @Override public void onStateChanged(LifecycleOwner source, Event event) { // Call ClassesInfoCache.CallbackInfo.invokeCallbacks() mInfo.invokeCallbacks(source, event, mWrapped); } }
And then chase ClassesInfoCache.CallbackInfo.invokeCallbacks() method.
void invokeCallbacks(LifecycleOwner source, Lifecycle.Event event, Object target) { // Not only the current lifecycle events, but also the on & any 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); } } } 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); } }
In fact, it's very simple. Reflection calls the lifecycle callback method of the onlifcycleevent annotation tag.
Wait For More
I want to go on to analyze the process life cycle, process Lifecycle owner and Lifecycle's cooperation using related source code, but the length of this article is a little too long. Please wait for the next one!
References and recommendations
The following articles are equally excellent. Read them carefully and recommend them to you.
- Beauty of Android architecture Lifecycle
- Jetpack and life cycle (3)
- Android lifecycle super parsing - things about the lifecycle
The article begins with the WeChat public number: Bing Xin said, focus on Java, Android original knowledge sharing, LeetCode solution.
More new original articles, scan and follow me!