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:
- Do not close the page until the time-consuming task is complete. After the time-consuming task is complete, view logs
- 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
-
Register fragments in ComponentActivity
-
AddObserver add listener method explanation
-
Fragment Indicates the callback of life cycle methods in the Fragment
-
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
- 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
- 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
- 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
- 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,
- 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).
- 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
- 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