Lifecycle usage and analysis of Jetpack components

Lifecycle usage and analysis of Jetpack components

What is Lifecycle?

Official explanation:

Lifecycle is a class that holds the information about the lifecycle state of a component (like an activity or a fragment) and allows other objects to observe this state.

Personal understanding: Lifecycle is a tool (class) that manages the life cycle of components (Activity/Fragment), and can monitor life cycle changes in other components (except Activity/Fragment). This component is a very important part of the Jetpack Architecture Components library (Jetpack Architecture Components), such as LiveData, ViewModel and other components, and must rely on this component to monitor and process life cycle changes.

How to use Lifecycle?

DefaultLifecycleObserver method: [recommended]

premise

  • The project is compiled with Java 8
  • Add gradle dependency "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
class LoginActivity : AppCompatActivity () { override fun onCreate (savedInstanceState: Bundle ?) { super .onCreate(savedInstanceState) setContentView(R.layout.activity_login) //Registration life cycle monitoring lifecycle.addObserver(ActivityLifecycleObserver()) } } /** * Life cycle monitoring class * Realize life cycle related logic, making the code logic in LoginActivity more concise */ class ActivityLifecycleObserver : DefaultLifecycleObserver{ override fun onResume (owner: LifecycleOwner ) { super .onResume(owner) //The life cycle is executed to onResume } } Copy code

Annotation method:

Not recommended. The annotation method is called by reflection, and there is a performance loss. class LoginActivity: AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState) setContentView(R.layout.activity_login)//Register lifecycle monitor lifecycle.addObserver(ActivityLifecycleObserver())}}

/** * Life cycle monitoring class * Realize life cycle related logic, making the code logic in LoginActivity more concise */ class ActivityLifecycleObserver : LifecycleObserver{ @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) fun onResume () { //The life cycle is executed to onResume } } Copy code

Expansion, self-management of life cycle

It is highly not recommended. This kind of self-maintaining life cycle may lead to race conditions.

class LoginActivity : AppCompatActivity () { private lateinit var mLifecycleRegistry: LifecycleRegistry override fun onCreate (savedInstanceState: Bundle ?) { super .onCreate(savedInstanceState) setContentView(R.layout.activity_login) //Customize LifecycleRegistry here mLifecycleRegistry = LifecycleRegistry( this ) mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE) //Registration life cycle monitoring lifecycle.addObserver(ActivityLifecycleObserver()) } override fun onStart () { super .onStart() //Send the life cycle through a custom LifecycleRegistry, which can override the default implementation mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START) } //This method must be rewritten to give a custom Registry override fun getLifecycle () : Lifecycle { return mLifecycleRegistry } } class ActivityLifecycleObserver : LifecycleObserver{ @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) fun onResume () { //The life cycle is executed to onResume } } Copy code

What is the principle of Lifecycle?

Understand Event, State

Before starting the source code explanation, we must first understand the relationship between Event and State. This is very important, because there are often mutual conversions between Event and State in the source code, and you need to rely on the relationship diagram () between the two to promote understanding.
Event: Lifecycle is an enumeration class that sends corresponding life cycle events, including life cycle events such as onCreate and onStart.
State: The life cycle state processed by Lifecycle, which has a mapping relationship with Event.

Realization principle

The principle only explains the Activity part and the implementation logic of Fragment. You can check the related calls and logic of the FragmentActivity # HostCallbacks class by yourself.
The source code part is based on lifecycle 2.2.0 version and acitivity 1.1.0 version.

The source code analysis is divided into two parts, starting from the calling method, knowing the internal logic in general, and then starting from the question to answer the doubts in the mind.

Starting from the calling method

/** * There are three parts here: lifecycle, addObserver(), ActivityLifecycleObserver object * lifecycle: the corresponding getLifecycle() method to obtain the Lifecycle object * addObserver(): call the addObserver() method of the Lifecycle object * ActivityLifecycleObserver object: This is our class object that implements the DefaultLifecycleObserver interface */ lifecycle.addObserver(ActivityLifecycleObserver()) Copy code

By calling the method, you can find that you need to look at the internal logic of the getLifecycle() and addObserver() methods?
The internal implementation of getLifecycle():
As you can see from the following code, the getLifecycle() method is actually implemented in ComponentActivity, and a LifecycleRegistry object is created and returned by this method.

public class ComponentActivity extends androidx . core . app . ComponentActivity implements LifecycleOwner { //... omitted... //Directly new a LifecycleRegistry object. //What does the LifecycleRegistry class do? We will look at this later. private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry( this ); //... omitted... @NonNull @Override public Lifecycle getLifecycle() { return mLifecycleRegistry; } //... omitted... } Copy code

The internal implementation of addObserver():
Through the code, you can find that LifecycleRegistry is the actual lifecycle management class, which is why the above getLifecycle() returns the LifecycleRegistry object. The code looks a lot, but it is also the most core part. A brief summary:

  1. The addObserver() method is called, an initial state is given internally, and it is bound to the observer (via ObserverWithState), and then the sync() method is called.
  2. The sync() method internally judges whether to go forward (forwardPass()) or backward (backwardPass()) based on the difference between the states. (Here we used to go as an example)
  3. forwardPass() internally calls the upEvent() method to convert the observer s State to Event, and then calls ObserverWithState#dispatchEvent() to dispatch.
  4. At this point, the Observer class we implemented ourselves will receive life cycle callbacks.

PS: Here you need to pay attention to LifecycleRegistry#mState and ObserverWithState#mState not to be confused.

public class LifecycleRegistry extends Lifecycle { //... omitted... @Override public void addObserver( @NonNull LifecycleObserver observer) { //Given an initial state, create an ObserverWithState object, pass in the state and observer, //then store the ObserverWithState object in the map State initialState = mState == DESTROYED? DESTROYED: INITIALIZED; ObserverWithState statefulObserver = new ObserverWithState(observer, initialState); ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver); //... omitted... if (!isReentrance) { //we do sync only on the top level. sync(); } //... omitted... } //... omitted... private void sync() { LifecycleOwner lifecycleOwner = mLifecycleOwner. get (); //... omitted... //Determine whether the state has been aligned through the isSynced() method. //The following logic is used to judge whether to go forward or backward. //Need to use "State and Event Relationship Diagram" to understand. //For example: //To display a newly created Activity, mState = Created, mObserverMap.eldest().getValue().mState = INITIALIZED, //newest.getValue().mState = INITIALIZED. It can be judged by the following logic to execute the forwardPass() method (go forward) while (!isSynced()) { 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); } } } //... omitted... 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); //The point is here~ Call the upEvent() method to get the Event corresponding to the current State, //Then call the dispatchEvent() method of ObserverWithState to dispatch observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState)); popParentState(); } } } //... omitted... //State to Event. Refer to "State and Event Relationship Diagram" to understand 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); } //... omitted... //Static inner class, used to bind observer and State static class ObserverWithState { State mState; LifecycleEventObserver mLifecycleObserver; ObserverWithState(LifecycleObserver observer, State initialState) { //Here we have done a layer conversion of the Observer class object that we have implemented. There is an internal realization of the annotation method, you can check it yourself. mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer); mState = initialState; } //Through the Event to State, the current Event event is issued, and the observer's State is updated void dispatchEvent(LifecycleOwner owner, Event event) { State newState = getStateAfter(event); mState = min(mState, newState); mLifecycleObserver.onStateChanged(owner, event); mState = newState; } } //... omitted... } Copy code

Start from the question

1. How does Lifecycle monitor the life cycle? How to notify other components (Observer) of life cycle changes?
From the above "start with calling method", I don't see how to monitor life cycle changes, so where is this piece of logic? (Here is an example of monitoring Activity life cycle) ReportFragment#injectIfNeededIn() is called in the ComponentActivity#onCreate() method. ReportFragment is the real life cycle provider (observed), it provides life cycle changes internally, and calls LifecycleRegistry#handleLifecycleEvent() method to issue. The handleLifecycleEvent() method internally converts the Event to the State, and then calls the sync method. The remaining logic is the same as in the "triggered from calling method" (see the internal implementation of addObserver() ).

public class ComponentActivity extends androidx . core . app . ComponentActivity implements LifecycleOwner, ViewModelStoreOwner, SavedStateRegistryOwner, OnBackPressedDispatcherOwner { //... omitted... @Override protected void onCreate( @Nullable Bundle savedInstanceState) { super .onCreate(savedInstanceState); mSavedStateRegistryController.performRestore(savedInstanceState); //Here ReportFragment.injectIfNeededIn( this ); if (mContentLayoutId != 0 ) { setContentView(mContentLayoutId); } } } //The actual life cycle is the observer public class ReportFragment extends Fragment { //... The life cycle related logic is omitted here, and dispatch() will be called at the end... private void dispatch(Lifecycle.Event event) { Activity activity = getActivity(); //... omitted... if (activity instanceof LifecycleOwner) { Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle(); if (lifecycle instanceof LifecycleRegistry) { //Call the LifecycleRegistry#handleLifecycleEvent() method to trigger the event ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event); } } } } public class LifecycleRegistry extends Lifecycle { //... omitted... public void handleLifecycleEvent( @NonNull Lifecycle.Event event) { //Get State according to the passed in Event State next = getStateAfter(event); moveToState(next); } //Update the value of LifecycleRegistry#mState, and then call the sync() method private void moveToState(State next) { //... omit... mState = next; //... omitted... sync(); } //... omitted... } Copy code

2. If addObserver() is called in onStart(), will it still be affected by the onCreate life cycle?
The conclusion can be drawn from the following code and comments: If you don't call addObserver() in onCreate(), you can still get life cycle events.

public class LifecycleRegistry extends Lifecycle { //... omitted... @Override public void addObserver( @NonNull LifecycleObserver observer) { //... omitted... //Here we start to compare the observer's State with the current State. If it is later than the current State, a dipatchEvent will be triggered to catch up with the current life cycle. //The significance of comparing two States is that if the addObserver() call is not in onCreate, you can still receive the onCreate life cycle. //For example: //The current State = Started, the observer's State = INITIALIZED, //the observer's State is later than the current State, then dispatchEvent(INITIALIZED) is triggered while ((statefulObserver.mState.compareTo(targetState) < 0 && mObserverMap.contains(observer))) { pushParentState(statefulObserver.mState); statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState)); popParentState(); //In order to prevent the current State from changing while the observer State is catching up, call calculateTargetState() to calculate the gap between the two again targetState = calculateTargetState(observer); } if (!isReentrance) { //we do sync only on the top level. sync(); } //... omitted... } //... omitted... } Copy code

3. The project now inherits the Activity class, how to use Lifecycle?
It can be known from the code that the life cycle change of Lifecycle is in ComponentActivity. If it is inherited from Activity, it can only maintain the life cycle changes by itself, which is similar to " extend and manage the life cycle independently ". The difference is that the LifecycleOwner interface needs to be implemented, and Maintain the entire life cycle. The following is the sample code:

open class BaseActivity : Activity (), LifecycleOwner{ private val mLifecycleRegistry = LifecycleRegistry( this ) override fun onCreate (savedInstanceState: Bundle ?) { super .onCreate(savedInstanceState) mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE) } override fun onStart () { super .onStart() mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START) } override fun onDestroy () { super .onDestroy() mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY) } override fun getLifecycle () : Lifecycle { return mLifecycleRegistry } } Copy code

summary

Briefly summarize the implementation principle of Lifecycle: call ReportFragment in ComponentActivity to monitor life cycle changes, and when the life cycle changes, call LifecycleRegistry#handleLifecycleEvent() to notify. Then call the LifecycleRegistry#addObserver() method, which will convert internally according to State and Event, and issue life cycle events. The following is a call sequence diagram, you can refer to the self-walking source code.