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 ~!