This is the 7th day of my participation in Gwen Challenge

Follow my public account: “Ananzhuo” to learn more knowledge

Lifecycle is used for what

Lifecycle is used to store information about the Lifecycle state of a component, such as an Activity or Fragment, and allow other objects to observe this state.

More generally, you can get all of our activity’s lifecycle method callbacks by registering callbacks

The following figure shows all types of mechanisms for observing the life cycle

Method of use

Overall LifeCycle is very simple to use and there is little to write about, with the usage methods section limited to absolute beginners.

It’s pointless to say so, but let’s start with a wave of simple code

The code shown

class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) lifecycle.addObserver(MainObserver()) } } class MainObserver : LifecycleObserver { @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) fun create(){ logEE("create") } @OnLifecycleEvent(Lifecycle.Event.ON_START) fun start(){ logEE("start") } @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) fun resume(){ logEE("resume") } @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) fun pause(){ logEE("pause") } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) fun stop(){ logEE("stop") } @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) fun  destroy(){ logEE("destroy") } @OnLifecycleEvent(Lifecycle.Event.ON_ANY) fun any(){ logEE("any") } }Copy the code

After running, we execute the following process: Start the app- click the back button to exit the app and check the life cycle log printing:

Results show

We find that all lifecycle callbacks are called, and that the ON_ANY annotated methods are called synchronously immediately after each lifecycle call

LifeCycle is used to handle the exception state

Description of Abnormal Status

Here’s an example of what I mean by abnormal states:

For example, we now start a time-consuming task to request the network, and then come back to update the UI after the network request is completed. Our abnormal state means that we actively shut down the activity before the network request is completed. This would normally cause a memory leak, and updating the UI again would obviously be an exception. In this case LifeCycle will be needed to resolve such an exception.

Methods used

lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)
Copy the code

Test case description and implementation

Case description:

Use Thread.sleep to simulate a 4s task in the onCreate method listener of the registered observer, and then listen for the callback of the task in the Activity and print the log. We need to simulate two operations:

  1. Do not close the page until the time-consuming task is complete. After the time-consuming task is complete, view logs
  2. Close the page before the time-consuming task is complete, and view logs after the time-consuming task is complete

The code shown

Register observer code for listening:

lifecycle.addObserver(MainObserver { runOnUiThread { if(lifecycle.currentState.isAtLeast(Lifecycle.State.CREATED)){ Tv.text =" Time-consuming task completed "logEE(" time-consuming task completed, UI updated successfully ")}else{logEE(" life cycle status mismatch, UI cannot be updated ")}}})Copy the code

Code to handle time-consuming tasks:

 @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    fun create(){
        thread {
            Thread.sleep(4000)
            fun0()
        }
    }
Copy the code

Logs corresponding to the two cases

Do not close the page and wait for time-consuming tasks to complete. After time-consuming tasks are complete, view logs:

Close the page before the time-consuming task is complete, and view logs after the time-consuming task is complete

conclusion

Is to use the LifeCycle of the LifeCycle. The currentState. IsAtLeast LifeCycle. State. (CREATED) method can determine the current State of the Activity, thus flexible processing abnormal State

LifeCycle implementation principle

The basic principle of

First, to outline the basic principles:

Our AppComponentActivity and FragmentActivity both inherit ComponentActivity.

ComponentActivity implements the LifecycleOwner interface.

A Fragment is added to the onCreate life cycle callback for ComponentActivity

So we use fragments to observe the life cycle

This kind of implementation mechanism is not uncommon, Glide, RxPremission for example are implemented in this way

I’ve generally divided the code presentation into the following four sections

  1. Register fragments in ComponentActivity

  2. AddObserver add listener method explanation

  3. Fragment Indicates the callback of life cycle methods in the Fragment

  4. How do I call back annotation methods

LifeCycle will be understood once LifeCycle is read and understood by putting these four parts together

Explain the four parts of the code

Register fragments in ComponentActivity

  1. Into fragments

AppComponentActivity

ReportFragment.injectIfNeededIn(this);
Copy the code
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();
        }
Copy the code

This is where you add the Fragment to your activity

AddObserver method explanation

  1. The method call

This method is called to the addObserver in LifecycleRegistry

@Override public void addObserver(@NonNull LifecycleObserver observer) { State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED; ObserverWithState statefulObserver = new ObserverWithState(observer, initialState); ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver); LifecycleOwner lifecycleOwner = mLifecycleOwner.get(); boolean isReentrance = mAddingObserverCounter ! = 0 || mHandlingEvent; State targetState = calculateTargetState(observer); mAddingObserverCounter++; 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--; }Copy the code

The ObserverWithState object is created to record the life cycle state,

State targetState = calculateTargetState(observer);

Method will calculate the life cycle state at this point,

This is followed by a while loop, which distributes the lifecycle state

For example, if you sign up in onResume, you can also receive callbacks from onCreate and onStart. This is actually a sticky registration. The radio receiver of battery information in Android is a good example of a sticky radio registration

The method calls in the following code are as follows

if (! isReentrance) { // we do sync only on the top level. sync(); }Copy the code

IsReentrance is false if no messages are currently being distributed in moveToState or if the number of registrants is not equal to 0. If this condition is met, the sync() method is called to distribute the message

Fragment Indicates the callback of life cycle methods in the Fragment

  1. Lifecycle method callback in ReportFragment

Such as:

dispatch(Lifecycle.Event.ON_DESTROY);
Copy the code
private void dispatch(Lifecycle.Event event) { Activity activity = getActivity(); *** if (activity instanceof LifecycleOwner) { Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle(); if (lifecycle instanceof LifecycleRegistry) { ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event); }}}Copy the code

Lifecycle callbacks will be distributed by calling the Dispatch method and lifecycle will continue to be distributed by calling the handleLifecycleEvent method within the Dispatch method

  1. Skip to the LifecycleRegistry class and find the handleLifecycleEvent method
 public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        State next = getStateAfter(event);
        moveToState(next);
    }
Copy the code

The getStateAfter method is used to confirm the state of the life cycle at which the event is triggered. There are three types:

CREATED, STARTED, DESTROYED

The moveToState method changes the lifecycle state and distributes it as follows:

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; }Copy the code

The sync() method in moveToState is used to distribute lifecycle events to the Observer,

  1. The sync () method
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

The following code shows several states of State

 public enum State {
      
        DESTROYED,
       
        INITIALIZED,
        
        CREATED,

        STARTED,

        RESUMED;
}
Copy the code

The sync method’s while loop contains the following code:

 if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
                backwardPass(lifecycleOwner);
            }
Copy the code

The preceding line of code compares the current lifecycle state to the state that was first added to the SafeIterableMap. If the value is less than zero (i.e., INITIALIZED is the first state added to the SafeIterableMap), the state must be DESTROYED. Note The current life cycle must be processed by backwardPass

Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest(); if (! mNewEventOccurred && newest ! = null && mState.compareTo(newest.getValue().mState) > 0) { forwardPass(lifecycleOwner); }Copy the code

In the code above, newest is the newest state added to the mObserverMap. If the current life cycle state is larger than that of newest, it indicates that the state is progressing (for example, onCreate to onStart).

  1. Continue with the backwardPass and forwardPass methods
private void forwardPass(LifecycleOwner lifecycleOwner) { Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator = mObserverMap.iteratorWithAdditions(); / / to get positive sequence of the iterator 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(); / / get the reverse iterator 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

Both forwardPass and backwardPass have three important lines of code:

pushParentState(getStateAfter(event));
observer.dispatchEvent(lifecycleOwner, event);
popParentState();
Copy the code

pushParentState(getStateAfter(event));

Saves the state to the list

observer.dispatchEvent(lifecycleOwner, event);

Distribute status to the Observer

popParentState();

Pops up the state saved in the previous code step

  1. Look at the dispathchEvent method
  void dispatchEvent(LifecycleOwner owner, Event event) {
            State newState = getStateAfter(event);
            mState = min(mState, newState);
            mLifecycleObserver.onStateChanged(owner, event);
            mState = newState;
        }
Copy the code

MLifecycleObserver here. OnStateChanged (the owner, the event); Will eventually callback to our statement of annotation methods, mLifecycleObserver examples are ReflectiveGenericLifecycleObserver, ReflectiveGenericLifecycleObserver eventually callback annotations by means of reflection method, this part of the next section will speak in detail

How do I call back annotation methods

In the addObserver method of the LifecycleRegistry class, we create an ObserverWithState object and place it in the Map

In fact, the annotation method is wrapped in the construction of the ObserverWithState method, resulting in the reflection callback method. Here’s how to start parsing the code:

The ObserverWithState method is constructed as follows

ObserverWithState(LifecycleObserver observer, State initialState) {
            mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
            mState = initialState;
        }
Copy the code

mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);

This one line of code that ultimately real type that is ReflectiveGenericLifecycleObserver mLifecycleObserver instance

The dispatchEvent method for ObserverWithState is as follows

void dispatchEvent(LifecycleOwner owner, Event event) {
            State newState = getStateAfter(event);
            mState = min(mState, newState);
            mLifecycleObserver.onStateChanged(owner, event);
            mState = newState;
        }
Copy the code

In the dispatchEvent method, is called

mLifecycleObserver.onStateChanged(owner, event);

Code for message distribution, is actually called ReflectiveGenericLifecycleObserver. OnStateChanged method.

So I can see ReflectiveGenericLifecycleObserver code in the class

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(LifecycleOwner source, Event event) { mInfo.invokeCallbacks(source, event, mWrapped); }}Copy the code

ReflectiveGenericLifecycleObserver class structure parameters of the wrapped object is registered in our addObserver custom Observer object.

The construction encapsulates the information in the Observer as a CallbackInfo object through some reflection operations.

And then when we call in ObserverWithState ReflectiveGenericLifecycleObserver onStateChanged method, is called the following code:

mInfo.invokeCallbacks(source, event, mWrapped);

The body of the invokeCallbacks method has been subsequently called as follows:

@SuppressWarnings("ConstantConditions") 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); }}}Copy the code

This whole stack of code ends up calling MethodReference

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

So this is the end point, the final pass

mMethod.invoke(target);

Executes our custom annotation method by calling the Java reflection method