The role of the Lifecycle

It is used to listen for the life cycle of activities and fragments, which is very useful and allows us to decouple some business code and monitor the life cycle more easily.

For example, I have a requirement to record the length of time that users view some pages and report it to the server.

This requirement can be fulfilled without Lifecycle

class RecordActivity : AppCompatActivity() { var startTime = 0L override fun onCreate(savedInstanceState: Bundle?) { startTime = System.currentTimeMillis() } override fun onDestroy() { val browseTime = System.currentTimeMillis() - StartTime // Reporting server... }}Copy the code

The above has realized the reporting of a page, but I need to report time for more than this interface. We might consider pulling this code out and putting it into BaseActivity, and then all activities inherit from BaseActivity, with a flag as a switch to whether to report. It’s nice, but it’s not elegant, it’s structurally altered, it’s intrusive.

How will Lifecycle be implemented?

class RecordActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { getLifecycle().addObserver(ReportObserver()) } } class ReportObserver : LifecycleObserver { var startTime = 0L @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) fun connectListener() { startTime = System.currentTimeMillis() } @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) fun disconnectListener() { val browseTime = System.currenttimemillis () -startTime // Reporting server... }}Copy the code

ReportObserver inherits LifecycleObserver with the annotation @onlifecycleEvent (…) Listening on ON_CREATE and ON_DESTROY to decouple is a much better implementation than the first.

Let’s see how it works.

Analysis of Lifecycle principle

Based on the lifecycle – common: 2.2.0

Step 1: ComponentActivity#getLifecycle()

In AppCompatActivity we can just call getLifecycle() and get the Lifecycle object, which is actually a method for ComponentActivity

public class ComponentActivity { private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this); public Lifecycle getLifecycle() { return mLifecycleRegistry; }}Copy the code

You can see that getLifecycle() returns the LifecycleRegistry object.

Step 2: LifecycleRegistry#addObserver()

Go inside LifecycleRegistry and take a look at the addObserver() method

@Override public void addObserver(@NonNull LifecycleObserver observer) { State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED; ObserverWithState statefulObserver = new ObserverWithState(observer, initialState); . while (...) {... statefulObserver.dispatchEvent(lifecycleOwner, event); . }... }Copy the code

The addObserver() method does not do any special processing inside the addObserver() method

 ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
Copy the code

Encapsulate the incoming observer as ObserverWithState

Further down is a while() loop, then dispatchEvent() sends something, and the Observer is added. The next step is to figure out when to trigger the Observer callback.

Step 3: Debug

In this step, I choose to observe a break point at the callback. Lifecycle.event. ON_CREATE is the entry point for analysis

The following method stack is obtained

 connectListener:28, ReportObserver (com.fun.sheet)
 invoke:-1, Method (java.lang.reflect)
 invokeCallback:216, ClassesInfoCache$MethodReference (androidx.lifecycle)
 invokeMethodsForEvent:194, ClassesInfoCache$CallbackInfo (androidx.lifecycle)
 invokeCallbacks:185, ClassesInfoCache$CallbackInfo (androidx.lifecycle)
 onStateChanged:37, ReflectiveGenericLifecycleObserver (androidx.lifecycle)
 dispatchEvent:354, LifecycleRegistry$ObserverWithState (androidx.lifecycle)
 forwardPass:265, LifecycleRegistry (androidx.lifecycle)
 sync:307, LifecycleRegistry (androidx.lifecycle)
 moveToState:148, LifecycleRegistry (androidx.lifecycle)
 handleLifecycleEvent:134, LifecycleRegistry (androidx.lifecycle)
 dispatch:68, ReportFragment (androidx.lifecycle)
 onActivityPostCreated:178, ReportFragment$LifecycleCallbacks (androidx.lifecycle)
 dispatchActivityPostCreated:1265, Activity (android.app)
 performCreate:8094, Activity (android.app)
 performCreate:8073, Activity (android.app)
 callActivityOnCreate:1320, Instrumentation (android.app)
 performLaunchActivity:3870, ActivityThread (android.app)
 handleLaunchActivity:4076, ActivityThread (android.app)
Copy the code

We know that starting an Activity is cross-process and that the Activity is managed by AMS.

So the bottom stack information

 handleLaunchActivity:4076, ActivityThread(android.app)
Copy the code

It’s the system method, in android.app, that goes from the bottom up, all the way to

 dispatchActivityPostCreated:1265, Activity (android.app)
Copy the code

Is system approach, by the method name, also can see dispatchActivityPostCreated () to distribute the Activity’s onCreate () event. Let’s take a look at the relevant code

Step 4: Activity# dispatchActivityPostCreated ()

Private void dispatchActivityPostCreated (@ Nullable Bundle savedInstanceState) {/ / collect all ActivityLifecycleCallbacks callback object Object[] callbacks = collectActivityLifecycleCallbacks(); if (callbacks ! = null) { for (int i = 0; i < callbacks.length; I++) {/ / of all the callback execution onActivityPostCreated () method ((Application. ActivityLifecycleCallbacks) callbacks[i]).onActivityPostCreated(this, savedInstanceState); }}... }Copy the code

This step is easy to understand and is the regular callback. Going back to the method stack image in Step 3, one pops up during the callback

 onActivityPostCreated:178, ReportFragment$LifecycleCallbacks (androidx.lifecycle)
Copy the code

Ah? Lifecycle is not android.app, but androidx.lifecycle. What is this ReportFragment? How does it successfully perform the callback? This question will be answered later as the code gets deeper, so let’s continue with the flow

Step 5: ReportFragment LifecycleCallbacks# onActivityPostCreated ()

Performed in step 4 is ReportFragment LifecycleCallbacks of onActivityPostCreated () method, is LifecycleCallbacks ReportFragment inner classes, It inherits from Application ActivityLifecycleCallbacks, its related code is as follows

 @Override
 public void onActivityPostCreated(@NonNull Activity activity,
         @Nullable Bundle savedInstanceState) {
     dispatch(activity, Lifecycle.Event.ON_CREATE);
 }
Copy the code

As you can see, this is a dispatch() method and the second argument passed in is Lifecycle.event.on_create. Then we follow the method stack in Step 3 to continue up

Step 6: ReportFragment#dispatch()

static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) { ... if (activity instanceof LifecycleOwner) { Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle(); If (lifecycle instanceof LifecycleRegistry) {lifecycle ((LifecycleRegistry) lifecycle). HandleLifecycleEvent (event); }}}Copy the code

We proceed to the ReportFragment# Dispatch () method, which executes the handleLifecycleEvent() method inside LifecycleRegistry, which continues to distribute events to LifecycleRegistry

Step 7: LifecycleRegistry#handleLifecycleEvent()

In this step, we follow the method stack information trace

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) { ... // Then call moveToState(event.gettarGetState ()); } private void moveToState(State next) { ... // call sync(); . } private void sync() { LifecycleOwner lifecycleOwner = mLifecycleOwner.get(); while (! IsSynced ()) {// There is no need to go deep into each line of code, just follow the main process, here omitted part of the code forwardPass(lifecycleOwner); } } private void forwardPass(LifecycleOwner lifecycleOwner) { ... while (...) { while (...) { ObserverWithState observer = entry.getValue(); // The dispatchEvent() method is called. // The observer is wrapped with ObserverWithState. ObserverWithState#dispatchEvent() observer.dispatchevent (lifecycleOwner, event); }}}Copy the code

Step 8: ObserverWithState#dispatchEvent()

//ObserverWithState is an internal class for LifecycleRegistry. Static class ObserverWithState {State mState; LifecycleEventObserver mLifecycleObserver; ReportObserver is wrapped as ObserverWithState, ObserverWithState(LifecycleObserver Observer, State initialState) {// ReportObserver in is called the Lifecycling. LifecycleEventObserver after () method within the ObserverWithState became lifecycleEventObserver kept mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer); mState = initialState; } void dispatchEvent(LifecycleOwner owner, Event Event) {... / / key method, and then step 9 mLifecycleObserver. OnStateChanged (the owner, the event); . }}Copy the code

There is more information in this step, but I will not expand it here, and I will analyze it later. Is mainly ObserverWithState constructor invoked the Lifecycling. LifecycleEventObserver () method, the object returned is lifecycleEventObserver, We can know the information according to the step 3 stack LifecycleEventObserver ReflectiveGenericLifecycleObserver point, that we continue to go down.

Step 9: ReflectiveGenericLifecycleObserver# onStateChanged ()

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 is an example of ClassesInfoCache's inner class CallbackInfo. MInfo. InvokeCallbacks (source, event, mWrapped); }}Copy the code

OnStateChanged () method calls the mInfo. InvokeCallbacks (), the mInfo is more clear, in the constructor of ReflectiveGenericLifecycleObserver also revealed that It is ClassesInfoCache. SInstance. GetInfo () returns the results, it is whether it first, continue to look at step 3 stack information, learn that mInfo refers to the inner class CallbackInfo ClassesInfoCache, continue to look down.

Step 10: ClassesInfoCache CallbackInfo# invokeCallbacks

void invokeCallbacks(LifecycleOwner source, Lifecycle.Event event, Object target) {// Continue calling invokeMethodsForEvent(mEventToHandlers. Get (event), 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 (MethodReference, ClassesInfoCache) {handlers (MethodReference, ClassesInfoCache); Handlers. Get (I). InvokeCallback (source, event, mWrapped); }}}Copy the code

This step is okay. Continue with step 11

Step 11: ClassesInfoCache MethodReference# invokeCallback ()

static final 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, 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 (...) {}}}Copy the code

Finally, we get to code 1, where mCallType is CALL_TYPE_NO_ARG. Call immediately after

 mMethod.invoke(target);
Copy the code

Obviously, this is called by reflection.

MMethod who is it?

Remember we had a custom method name in ReportObserver called connectListener(), and here is the reference to that method

Who is the target?

ReportObserver itself, of course.

At this point, the entire callback flow has been analyzed.

The overall process is a custom method in ReportObserver with a specific lifecycle annotation. Reflection will be called to get a reference to this method. When AMS starts the Activity, it will notify all listeners to call back the corresponding lifecycle method. The ReportFragment is the entry point for handling the lifecycle method, which eventually completes the callback.

The process is over, but we’re left with a lot of problems to solve. So keep going

Question 1: Where is reflection performed? How is the mMethod reference initialized

Let’s go back to step 2

 ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
Copy the code

We mentioned that ReportObserver is packaged as ObserverWithState, which seems to be multiple times, but actually it is not. In Step 8 we posted the constructor for ObserverWithState, so I’ll do it again

static class ObserverWithState { State mState; LifecycleEventObserver mLifecycleObserver; ObserverWithState (LifecycleObserver observer and State initialState) {/ / in the constructor calls the Lifecycling lifecycleEventObserver (), The parameter passed in is ReportObserver. mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer); mState = initialState; }}Copy the code

Here Lifecycling. LifecycleEventObserver (the observer), it is necessary for us to analyze

Mark 1 – Lifecycling. LifecycleEventObserver ()

@NonNull static LifecycleEventObserver lifecycleEventObserver(Object object) { ... final Class<? > klass = object.getClass(); / / code 1 int type = getObserverConstructorType (klass); If (type == GENERATED_CALLBACK) {//GENERATED_CALLBACK is 2... return new CompositeGeneratedAdaptersObserver(adapters); } return new ReflectiveGenericLifecycleObserver(object); }Copy the code

Indicating the code 1, getObserverConstructorType (klass) worthy of our attention, seems to be the handling of class object, and returns the type will influence next return values

Mark 2 – Lifecycling. GetObserverConstructorType ()

private static int getObserverConstructorType(Class<? > klass) { ... int type = resolveObserverCallbackType(klass); . Omit cache logic return type; }Copy the code

Continue to follow up resolveObserverCallbackType ()

Mark 3 – Lifecycling. ResolveObserverCallbackType ()

private static int resolveObserverCallbackType(Class<? > klass) { ... // The first step is to generate the Constructor without concern for Constructor<? extends GeneratedAdapter> constructor = generatedConstructor(klass); if (constructor ! = null) { ... return GENERATED_CALLBACK; } / / the second step is to determine whether there is life cycle method Boolean hasLifecycleMethods = ClassesInfoCache. SInstance. HasLifecycleMethods (klass); if (hasLifecycleMethods) { return REFLECTIVE_CALLBACK; }... }Copy the code

Notice that the valid information is coming in. The second step of processing introduces the ClassesInfoCache class, which is exactly what we’re looking for, by calling the hasLifecycleMethods() method of ClassesInfoCache

Tag 4-classesInfocache #hasLifecycleMethods()

boolean hasLifecycleMethods(Class<? > klass) { ... ReportObserver [] methods = getDeclaredMethods(klass); ReportObserver [] methods = getDeclaredMethods(klass); for (Method method : OnLifecycleEvent annotation = method.getannotation (onlifecycleEvent.class); if (annotation ! = null) {createInfo(klass, methods); return true; }}... Cache logic return false; }Copy the code

ConnectListener () in ReportObserver is annotated with @onlifecycleEvent, so call createInfo(klass, methods) and return true. Look at the createInfo(Klass, methods) method

Tag 5-classesInfocache# createInfo()

private CallbackInfo createInfo(Class<? > klass, @Nullable Method[] declaredMethods) { ... for (Method method : methods) { OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class); . Class<? >[] params = method.getParameterTypes(); int callType = CALL_TYPE_NO_ARG; If (params.length > 0) {callType = CALL_TYPE_PROVIDER; if (params.length > 0) {callType = CALL_TYPE_PROVIDER; . } if (params.length > 1) { callType = CALL_TYPE_PROVIDER_WITH_EVENT; . } if (params.length > 2) { ... } // code 1 MethodReference MethodReference = new MethodReference(callType, method); CallbackInfo info = new CallbackInfo(handlerToEvent); return info; }Copy the code

After removing the irrelevant logic, you see the concrete code. Code 1 initializes MethodReference, code 2 initializes CallbackInfo and returns INFO, but the INFO object is not received by the code in tag 4, This is because creating MethodReference and CallbackInfo will be cached in a Map, but I’ve omitted this part of the code.

The end

The invocation chain is over here, mark 3 return type is REFLECTIVE_CALLBACK, until the mark 1 returns the ReflectiveGenericLifecycleObserver, Therefore, it is concluded that reflection is performed in ClassesInfoCache and information about ReportObserver is saved

Problem 2: Source of ReportFragment

In step 4, there was a strange jump from Android.app to Androidx.Lifecycle. Their bridge was The ReportFragment. In that case, we needed to look at the ReportFragment and we knew for sure that ReportFragment have Application. ActivityLifecycleCallbacks related code. In Step 5, we already knew some of the code, so let’s take a look at it

 static class LifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
     @Override
     public void onActivityCreated(@NonNull Activity activity,
             @Nullable Bundle bundle) {
     }
     @Override
     public void onActivityPostCreated(@NonNull Activity activity,
             @Nullable Bundle savedInstanceState) {
         dispatch(activity, Lifecycle.Event.ON_CREATE);
     }
     @Override
     public void onActivityStarted(@NonNull Activity activity) {
     }
     @Override
     public void onActivityPostStarted(@NonNull Activity activity) {
         dispatch(activity, Lifecycle.Event.ON_START);
     }
     @Override
     public void onActivityResumed(@NonNull Activity activity) {
     }
     @Override
     public void onActivityPostResumed(@NonNull Activity activity) {
         dispatch(activity, Lifecycle.Event.ON_RESUME);
     }
     @Override
     public void onActivityPrePaused(@NonNull Activity activity) {
         dispatch(activity, Lifecycle.Event.ON_PAUSE);
     }
     @Override
     public void onActivityPaused(@NonNull Activity activity) {
     }
     @Override
     public void onActivityPreStopped(@NonNull Activity activity) {
         dispatch(activity, Lifecycle.Event.ON_STOP);
     }
     @Override
     public void onActivityStopped(@NonNull Activity activity) {
     }
     @Override
     public void onActivitySaveInstanceState(@NonNull Activity activity,
             @NonNull Bundle bundle) {
     }
     @Override
     public void onActivityPreDestroyed(@NonNull Activity activity) {
         dispatch(activity, Lifecycle.Event.ON_DESTROY);
     }
     @Override
     public void onActivityDestroyed(@NonNull Activity activity) {
     }
 }
Copy the code

So where is LifecycleCallbacks registered? We looked it up and found a method like this

ReportFragment#injectIfNeededIn()

public static void injectIfNeededIn(Activity activity) { if (Build.VERSION.SDK_INT >= 29) { activity.registerActivityLifecycleCallbacks( new LifecycleCallbacks()); } android.app.FragmentManager manager = activity.getFragmentManager(); if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) { manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit(); manager.executePendingTransactions(); }}Copy the code

This code is very clear, register LifecycleCallbacks if the SDK is on top of 29, and add a ReportFragment() for compatibility to keep things working below 29. Wonderful! But Glide has been used for a long time

Where is injectIfNeededIn() called

ComponentActivity#onCreate()

 @Override
 protected void onCreate(@Nullable Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     ReportFragment.injectIfNeededIn(this);
 }
Copy the code

It’s registered in the onCreate() method for ComponentActivity. So it’s not surprising that The ReportFragment can receive events.

Question 3: Why do callbacks registered in the onCreate() method still receive the ON_CREATE event?

ReportObserver() is registered in the RecordActivity onCreate() method.

 class RecordActivity : AppCompatActivity() {
 ​
     override fun onCreate(savedInstanceState: Bundle?) {
         getLifecycle().addObserver(ReportObserver())
     }
 ​
 }
Copy the code

In fact, we can find the answer in the method stack, step 3, let’s review again, here are the underlying method execution steps

. onActivityPostCreated:178, ReportFragment$LifecycleCallbacks (androidx.lifecycle) dispatchActivityPostCreated:1265, Activity (android.app) performCreate:8094, Activity (android.app) performCreate:8073, Activity (android.app) callActivityOnCreate:1320, Instrumentation (android.app) performLaunchActivity:3870, ActivityThread (android.app) handleLaunchActivity:4076, ActivityThread (android.app)Copy the code

In performing dispatchActivityPostCreated before () method, carried out the Activity performCreate () method, we take a look at

Activity#performCreate()

@UnsupportedAppUsage final void performCreate(Bundle icicle, PersistableBundle persistentState) {/ / first is front-facing callback dispatchActivityPreCreated (bonnie); . // The onCreate callback if (persistentState! = null) { onCreate(icicle, persistentState); } else { onCreate(icicle); }... / / rear is finally Created the callback, it is this correction, let the Observer has received the onCreate event dispatchActivityPostCreated (bonnie); }Copy the code

It is learned that the original onCreate event distribution has several, first is dispatchActivityPreCreated, just call it lead the callback, and then the onCreate (), which is our common callback. Finally the dispatchActivityPostCreated (), please call it rear callback, we register is the rear event callback. So it is ~!