For Android Developer today, Google Jetpack is one of the most fundamental architectural components. Since its launch, it has dramatically changed our development model and made it easier to develop, which requires a certain level of understanding of how some of the sub-components work. So I decided to write a series of articles on Jetpack source code parsing, which I hope will help you 😇😇
Public number: byte array
Series article navigation
- Jetpack (1) – Lifecycle
- Jetpack (2) -Lifecycle derivatives
- Jetpack (3) – LiveData source code in detail
- Jetpack (4) – LiveData derivatives source code in detail
- Jetpack (5) – Startup
- Jetpack (6) – ViewModel
- Jetpack (7) – SavedStateHandle
Lifecycle is one of the most fundamental aspects of the Jetpack family. Lifecycle makes it much easier and more efficient for developers to build business logic that is dependent on Lifecycle changes. This allows us to listen for changes in the life cycle of activities, fragments, services, and even processes in a unified way, and greatly reduces the risk of memory leaks and NPES in business code. This article will give Lifecycle a comprehensive look at the source code that I hope will help you 😇😇
The source code described in this article is based on the current latest releases of the following dependency libraries:
implementation 'androidx. Appcompat: appcompat: 1.2.0'
implementation "Androidx. Lifecycle: lifecycle - common: 2.2.0." "
implementation "Androidx. Lifecycle: lifecycle - common - java8:2.2.0." "
implementation "Androidx. Lifecycle: lifecycle - runtime: 2.2.0." "
Copy the code
A, Lifecycle
1, how to use
Today, if we want to manage our business logic based on changes in the Activity’s life cycle state, we can easily use the following method to listen. Event notification is in the form of callback interface methods that are invoked before or after each Activity lifecycle method is triggered
override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onCreate(owner: LifecycleOwner){}override fun onResume(owner: LifecycleOwner){}override fun onDestroy(owner: LifecycleOwner){}})}Copy the code
In addition, there is a callback method based on the @onlifecycleEvent annotation. This method does not require the method name, but has specific requirements for the type, order, and number of input parameters of the method, which will be described in a later section. This approach is aimed at Java 7 as a compiled version of the platform, but will be phased out in the future, and Google officials also recommend that developers use the form of interface callbacks as much as possible
lifecycle.addObserver(object : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onCreateEvent(lifecycleOwner: LifecycleOwner){}@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroyEvent(lifecycleOwner: LifecycleOwner){}@OnLifecycleEvent(Lifecycle.Event.ON_ANY)
fun onAnyEvent(lifecycleOwner: LifecycleOwner, event: Lifecycle.Event){}})Copy the code
2, the source code
Lifecycle is an abstract class and the logic itself is relatively simple, and most of the time we will be exposed to its subclass LifecycleRegistry. Lifecycle contains only one global variable, three abstract methods, and two enumerated classes
mInternalScopeRef
Used in the introductionlifecycle-common-ktx
The package case, which is only useful when using the Kotlin coroutine library, is ignored here- The three abstract methods are used to add LifecycleObserver, remove LifecycleObserver, and get the value of the state that Lifecycle is currently in
- The Event class is used to abstract events that correspond to changes in Activity/Fragment life cycle events. For example, when the Activity’s
onCreate
Methods are abstracted when called back toON_CREATE
The event - The State class is used to mark the current Lifecycle State of Lifecycle. For example, when the Activity is about to callback
onDestory
Method is inDESTROYED
state
public abstract class Lifecycle {
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@NonNull
AtomicReference<Object> mInternalScopeRef = new AtomicReference<>();
@MainThread
public abstract void addObserver(@NonNull LifecycleObserver observer);
@MainThread
public abstract void removeObserver(@NonNull LifecycleObserver observer);
@MainThread
@NonNull
public abstract State getCurrentState(a);
public enum Event {
ON_CREATE,
ON_START,
ON_RESUME,
ON_PAUSE,
ON_STOP,
ON_DESTROY,
ON_ANY
}
@SuppressWarnings("WeakerAccess")
public enum State {
DESTROYED,
INITIALIZED,
CREATED,
STARTED,
RESUMED;
public boolean isAtLeast(@NonNull State state) {
return compareTo(state) >= 0; }}}Copy the code
2. Related interfaces
Lifecycle will provide many event callbacks and type definitions in the form of interfaces. Here are some of the interfaces that will be used frequently by developers and what they can do
1, LifecycleOwner
LifecycleOwner interface is used to flag that its implementation class has a Lifecycle object, which means that the implementation class has a Lifecycle. We daily use androidx. Appcompat. App. AppCompatActivity and androidx fragments. The app. The fragments are implements this interface
public interface LifecycleOwner {
@NonNull
Lifecycle getLifecycle(a);
}
Copy the code
2, LifecycleObserver
LifecycleObserver is an empty interface, and most of the time it’s the subinterfaces that are really useful. LifecycleObserver is only for type markup, so to speak
public interface LifecycleObserver {}Copy the code
1, LifecycleEventObserver
LifecycleEventObserver is used to listen for Lifecycle changes and get specific changes to Lifecycle events
public interface LifecycleEventObserver extends LifecycleObserver {
void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event);
}
Copy the code
2, FullLifecycleObserver
FullLifecycleObserver extends several abstract methods of the same name based on the Activity lifecycle callback method, which can be seen as a more concrete event splitting for LifecycleEvening Server
interface FullLifecycleObserver extends LifecycleObserver {
void onCreate(LifecycleOwner owner);
void onStart(LifecycleOwner owner);
void onResume(LifecycleOwner owner);
void onPause(LifecycleOwner owner);
void onStop(LifecycleOwner owner);
void onDestroy(LifecycleOwner owner);
}
Copy the code
3, DefaultLifecycleObserver
The DefaultLifecycleObserver interface inherits from FullLifecycleObserver, and DefaultLifecycleObserver implements all the methods of the parent interface by default. Most of the time we only need one or two notifications of life cycle events, and the presence of DefaultLifecycleObserver allows us to override the methods of the parent interface on demand without having to implement all the abstract methods. The interface’s ability to declare default methods has only been available since Java 8, so use DefaultLifecycleObserver only if your project is compiled for Java 8. If we use FullLifecycleObserver we have to implement all the abstract methods
public interface DefaultLifecycleObserver extends FullLifecycleObserver {
@Override
default void onCreate(@NonNull LifecycleOwner owner) {}@Override
default void onStart(@NonNull LifecycleOwner owner) {}@Override
default void onResume(@NonNull LifecycleOwner owner) {}@Override
default void onPause(@NonNull LifecycleOwner owner) {}@Override
default void onStop(@NonNull LifecycleOwner owner) {}@Override
default void onDestroy(@NonNull LifecycleOwner owner) {}}Copy the code
DefaultLifecycleObserver contained in androidx. Lifecycle: lifecycle – common – java8: XXX the dependence of the rolls, the library also contains only the interface, The naming of the dependent library also indicates that it is intended for the Java 8 platform. Google also recommends that developers use DefaultLifecycleObserver as much as possible, as Java 8 will eventually become the mainstream of Android development, and annotations for life cycle callbacks in Java 7 will eventually become obsolete
4, FullLifecycleObserverAdapter
FullLifecycleObserverAdapter LifecycleEventObserver interface is achieved, This function is used to forward events to FullLifecycleObserver and LifecycleEventObserver when Lifecycle Lifecycle event status changes are received
class FullLifecycleObserverAdapter implements LifecycleEventObserver {
private final FullLifecycleObserver mFullLifecycleObserver;
private final LifecycleEventObserver mLifecycleEventObserver;
FullLifecycleObserverAdapter(FullLifecycleObserver fullLifecycleObserver,
LifecycleEventObserver lifecycleEventObserver) {
mFullLifecycleObserver = fullLifecycleObserver;
mLifecycleEventObserver = lifecycleEventObserver;
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
switch (event) {
case ON_CREATE:
mFullLifecycleObserver.onCreate(source);
break;
case ON_START:
mFullLifecycleObserver.onStart(source);
break;
case ON_RESUME:
mFullLifecycleObserver.onResume(source);
break;
case ON_PAUSE:
mFullLifecycleObserver.onPause(source);
break;
case ON_STOP:
mFullLifecycleObserver.onStop(source);
break;
case ON_DESTROY:
mFullLifecycleObserver.onDestroy(source);
break;
case ON_ANY:
throw new IllegalArgumentException("ON_ANY must not been send by anybody");
}
if(mLifecycleEventObserver ! =null) { mLifecycleEventObserver.onStateChanged(source, event); }}}Copy the code
Third, ReportFragment
Again, how do we implement Lifecycle listening for activities today
override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycle.addObserver(object : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
when (event) {
Lifecycle.Event.ON_CREATE -> TODO()
Lifecycle.Event.ON_START -> TODO()
Lifecycle.Event.ON_RESUME -> TODO()
Lifecycle.Event.ON_PAUSE -> TODO()
Lifecycle.Event.ON_STOP -> TODO()
Lifecycle.Event.ON_DESTROY -> TODO()
Lifecycle.Event.ON_ANY -> TODO()
}
}
})
}
Copy the code
LifecycleEventObserver is a LifecycleEventObserver that will change the state of the Lifecycle. Or, who called back onStateChanged?
Now we use in daily development Activity tend to be inherited in androidx appcompat. Appcompat: XXX AppCompatActivity in this package, And AppCompatActivity will eventually inherit at androidx.core.app.Com ponentActivity, ComponentActivity onCreate method is as follows:
@SuppressLint("RestrictedApi")
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ReportFragment.injectIfNeededIn(this);
}
Copy the code
Lifecycleevening Server can receive all of the Activity’s Lifecycle. Events via the ReportFragment. Here’s a closer look at the ReportFragment internal source code to see the implementation logic step by step
InjectIfNeededIn () is a static method that takes an Android.app.activity object as an input parameter
public static void injectIfNeededIn(Activity activity) {
if (Build.VERSION.SDK_INT >= 29) {
// On API 29+, we can register for the correct Lifecycle callbacks directly
// When the API level is 29+, we can register the lifecycle callback directly with Android.app. Activity
activity.registerActivityLifecycleCallbacks(
new LifecycleCallbacks());
}
// Prior to API 29 and to maintain compatibility with older versions of
// ProcessLifecycleOwner (which may not be updated when lifecycle-runtime is updated and
// need to support activities that don't extend from FragmentActivity from support lib),
// use a framework fragment to get the correct timing of Lifecycle events
// Prior to API 29, add an invisible fragment to the activity to get the correct callback for the activity life cycle event
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
The injectIfNeededIn() method does event distribution in two cases:
- The system version of the running device must be less than 29. This situation indirectly gets callback notifications for the Activity’s various life cycle events by adding a ReportFragment without a UI to the Activity
- The system version of the running device must be greater than or equal to 29. This case registers a LifecycleCallbacks with the Activity to get callback notifications directly for each lifecycle event. The operations in the first case are also performed
To distinguish between the two cases, because registerActivityLifecycleCallbacks started android SDK 29. The app. The new method of adding the Activity, Getting event notifications directly from LifecycleCallbacks is supported starting with this release. If the user has a device SDK version less than 29, they still need to obtain event notifications indirectly through ReportFragment
1, SDK >= 29
So LifecycleCallbacks, Lifecycle.Event.ON_XXX will send an Event value through dispatch(Activity, Lifecycle. An Event value is sent before onPause, onStop, and onDestroy are called
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 onActivityPreDestroyed(@NonNull Activity activity) {
dispatch(activity, Lifecycle.Event.ON_DESTROY);
}
@Override
public void onActivityDestroyed(@NonNull Activity activity) {}}Copy the code
Once the Dispatch () method gets the Event value, Lifecycle object will be retrieved from the Activity and LifecycleRegistry object will be retrieved from the type judgment, The Event value is eventually passed by calling the handleLifecycleEvent() method, allowing the outside world to be notified of each lifecycle Event
@SuppressWarnings("deprecation")
static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) {
//LifecycleRegistryOwner deprecated, see LifecycleOwner
if (activity instanceof LifecycleRegistryOwner) {
((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
return;
}
if (activity instanceof LifecycleOwner) {
Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
if (lifecycle instanceofLifecycleRegistry) { ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event); }}}Copy the code
From this also can guess, androidx. Appcompat. App. AppCompatActivity implements is LifecycleRegistry LifecycleOwner interface to return the Lifecycle of objects, Actually androidx. Fragments. App. Fragments as well
2. SDK < 29
Again, take a look at how the ReportFragment added to the Activity works. Since the ReportFragment is attached to the Activity, the Lifecycle method of the ReportFragment itself is associated with the Activity in which it is located. The Activity is indirectly notified of its Lifecycle events by calling the Lifecycle method dispatch.event.on_xxxx in the corresponding ReportFragment Lifecycle method to send the corresponding Event value
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); ... dispatch (Lifecycle. Event. ON_CREATE); }@Override
public void onStart(a) {
super.onStart(); ... dispatch (Lifecycle. Event. ON_START); }@Override
public void onDestroy(a) {
super.onDestroy(); dispatch(Lifecycle.Event.ON_DESTROY); ...}Copy the code
The Dispatch () method internally determines the version number of the target device to determine whether or not the Event value is actually distributed, avoiding duplicate sending with LifecycleCallbacks when the SDK version number is greater than 29
private void dispatch(@NonNull Lifecycle.Event event) {
if (Build.VERSION.SDK_INT < 29) { dispatch(getActivity(), event); }}Copy the code
In this way, The ReportFragment forwards the Event value of the Activity externally using the above logic
Four, LifecycleRegistry
LifecycleRegistry’s handleLifecycleEvent(Lifecycle.Event) method is called by the ReportFragment when Lifecycle. Now that the required Event value is available, how does LifecycleRegistry forward the Event value to the LifecycleObserver
LifecycleRegistry is an important class within the Lifecycle family that blocks specific types of life-cycle holding classes (activities/fragments, etc.). LifecycleRegistry implements specific event callbacks and state management, allowing external entities (activities/fragments, etc.) to only forward lifecycle events. Androidx.activity.Com ponentActivity and androidx. Fragments. App. Use the LifecycleRegistry fragments
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
LifecycleOwner.ViewModelStoreOwner.HasDefaultViewModelProviderFactory.SavedStateRegistryOwner.OnBackPressedDispatcherOwner {
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
@NonNull
@Override
public Lifecycle getLifecycle(a) {
returnmLifecycleRegistry; }}public class Fragment implements ComponentCallbacks.OnCreateContextMenuListener.LifecycleOwner.ViewModelStoreOwner.HasDefaultViewModelProviderFactory.SavedStateRegistryOwner {
LifecycleRegistry mLifecycleRegistry;
@Override
@NonNull
public Lifecycle getLifecycle(a) {
returnmLifecycleRegistry; }}Copy the code
Before we look at the implementation logic of LifecycleRegistry, we need to have a general understanding of where LifecycleRegistry is positioned and what it must do. We can reverse the steps required to achieve the desired effect:
- LifecycleOwner interfaces can be implemented not only for activities and fragments, but also for services, dialogs and other classes that have a lifecycle. Regardless of LifecycleOwner’s implementation class, the functionality and logic required for LifecycleOwner itself are the same: addObserver, removeObserver, getCurrentState, observers for repeated events, and so on. So Google will need to provide a common Lifecycle implementation class to simplify the cost of implementing the LifecycleOwner interface. The final implementation class is LifecycleRegistry. (Let’s assume that there is only one Activity that needs to implement the LifecycleOwner interface.)
- LifecycleRegistry needs to hold the LifecycleOwner object to determine whether callbacks can be made to it, but you cannot directly strong-reference LifecycleOwner to avoid memory leaks
- LifecycleRegistry triggers two types of Event values to publish to the Observer:
- A new Observer is added to which you need to synchronize the Activity’s current State value. For example, if a LifecycleEventObserver is added to an Activity when it is in a RESUMED state, you must synchronize the current state value to the LifecycleEventObserver, So LifecycleEventObserver will receive CREATED, STARTED, and RESUMED events
- The Activity’s lifecycle State has changed and the latest State value needs to be synchronized to the Observer
With that in mind, take a look at the general logic of LifecycleRegistry
LifecycleRegistry is naturally a subclass of Lifecycle, whose constructor needs to be passed in the LifecycleOwner object
public class LifecycleRegistry extends Lifecycle {
//mState marks the current lifecycle state of the LifecycleOwner object
private State mState;
// Hold a weak reference to LifecycleOwner to avoid memory leaks
private final WeakReference<LifecycleOwner> mLifecycleOwner;
public LifecycleRegistry(@NonNull LifecycleOwner provider) {
mLifecycleOwner = newWeakReference<>(provider); mState = INITIALIZED; }}Copy the code
The main logic of the addObserver() method is: Wrap the incoming Observer object with type ObserverWithState, Conveniently, LifecycleObserver (Java 7) in the form of ** annotations and LifecycleObserver (Java 8) in the interface implementation ** unify the entry to the dispatchEvent() method for state call-back. In addition, since LifecycleObserver will probably be in an uninitialized state when Lifecycle is added, the Event value needs to be progressively delivered to ObserverWithState through a loop check
//Lifecycle adds the @mainThread annotation to the addObserver method, meaning that this method can only be used for MainThread calls
// Multithreading is not considered here
@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);
if(previous ! =null) {
// If the observer has been passed in before, it is not added again and returns directly
return;
}
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
if (lifecycleOwner == null) {
// If the LifecycleOwner object has already been reclaimed, it is returned directly
return;
}
// If isReentrance is true, reentry is present:
//1. mAddingObserverCounter ! = 0. This happens because the developer added a LifecycleObserver first, and while the event was being called back to it, called the addObserver method in the callback method to add a new LifecycleObserver
/ / 2. MHandlingEvent to true. That is, Lifecycle.Event is being called outward
booleanisReentrance = mAddingObserverCounter ! =0 || mHandlingEvent;
State targetState = calculateTargetState(observer);
// Add one to indicate that you are currently in the process of calling back the Event value to the newly added LifecycleObserver
mAddingObserverCounter++;
/ / statefulObserver.mState.com pareTo (targetState) < 0 up shows the State value not traverse to the target State
Contains (Observer) contains(observer) has not been removed
// Since it is possible that the developer voluntarily removed the observer in the callback method during the loop, this loop is checked each time
while ((statefulObserver.mState.compareTo(targetState) < 0
&& mObserverMap.contains(observer))) {
// Save the current state value mState that the Observer has traversed
pushParentState(statefulObserver.mState);
// Calls back to the Observer the Event value to be received before entering stateFulobServer. mState
statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
/ / remove 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 process of calling back events to LifecycleObserver can be shown in the official figure below
- Assume the current LifecycleRegistry
mState
Is in the RESUMED stateaddObserver
The newly added LifecycleObserver method is wrapped as ObserverWithState and INITIALIZED to INITIALIZED. Because RESUMED is greater than INITIALIZED, object with state isINITIALIZED -> CREATED -> STARTED -> RESUMED
Receive event notifications in this order - Assume the current LifecycleRegistry
mState
In the STARTED state. If LifecycleRegistry receives the ON_RESUME event,mState
I need to change to RESUMED; If LifecycleRegistry receives the ON_STOP event,mState
You need to change to “CREATED”; So, LifecycleRegistrymState
They migrate in different directions
ObserverWithState passes the LifecycleObserver object to Lifecycling for type-wrapping, syntheses the reflection logic and interface callback logic into a new LifecycleEventObserver object, So as to make the Event distribution are unified to mLifecycleObserver onStateChanged
static class ObserverWithState {
State mState;
LifecycleEventObserver mLifecycleObserver;
ObserverWithState(LifecycleObserver observer, State initialState) {
mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
mState = initialState;
}
void dispatchEvent(LifecycleOwner owner, Event event) { State newState = getStateAfter(event); mState = min(mState, newState); mLifecycleObserver.onStateChanged(owner, event); mState = newState; }}Copy the code
As mentioned earlier, LifecycleRegistry ends up calling the handleLifecycleEvent(Lifecycle.Event) method of the LifecycleRegistry object when Lifecycle. The method converts the State value from the received Event value, updates the local mState, notifes all observers of the Event, and finally calls the dispatchEvent method with ObserverWithState. So we’ll just focus on the dispatchEvent method later
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
State next = getStateAfter(event);
moveToState(next);
}
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
To note is that of androidx. Fragments. The app. The fragments of life cycle events need to use to LifecycleRegistry listening, The Fragment itself eventually does its own LifecycleEvent notification by calling its handleLifecycleEvent(Lifecycle.Event) method. The code is relatively simple and won’t be described here
Fifth, Lifecycling
As mentioned above, LifecycleRegistry will wrap all LifecycleObserver that is passed in externally into LifecycleEventObserver objects according to Lifecycling. Let’s first explain why this packaging is necessary
- LifecycleEventObserver and FullLifecycleObserver are both interfaces inherited from LifecycleObserver. Custom observers implemented by developers may implement both interfaces or either. LifecycleRegistry must call back to all interface methods that exist when an event is triggered
- In addition to implementing callbacks through interface methods, Google also provides a way to implement callbacks through annotations, in which case you need to implement callbacks through reflection
LifecycleRegistry classes are very bloated if you use them to make type judgments, interface callbacks, and reflection calls to external observers. So Lifecycling’s role is to encapsulate this set of logic, and simply opening a onStateChanged method will allow LifecycleRegistry to complete the event distribution, making the process much clearer and more accountable
Now let’s look at the logic of the Life Cleeve Server method
@NonNull
static LifecycleEventObserver lifecycleEventObserver(Object object) {
// Corresponds to the first point above
boolean isLifecycleEventObserver = object instanceof LifecycleEventObserver;
boolean isFullLifecycleObserver = object instanceof FullLifecycleObserver;
if (isLifecycleEventObserver && isFullLifecycleObserver) {
// If object inherits both LifecycleEventObserver and FullLifecycleObserver interfaces
/ / will forward its packaging for FullLifecycleObserverAdapter object to events
return new FullLifecycleObserverAdapter((FullLifecycleObserver) object,
(LifecycleEventObserver) object);
}
if (isFullLifecycleObserver) {
/ / same as above
return new FullLifecycleObserverAdapter((FullLifecycleObserver) object, null);
}
if (isLifecycleEventObserver) {
// Object is already the desired target type (LifecycleEventObserver), just return as is
return (LifecycleEventObserver) object;
}
// Corresponds to the second point mentioned above, namely reflection operation
finalClass<? > klass = object.getClass();int type = getObserverConstructorType(klass);
if (type == GENERATED_CALLBACK) {
List<Constructor<? extends GeneratedAdapter>> constructors =
sClassToAdapters.get(klass);
if (constructors.size() == 1) {
GeneratedAdapter generatedAdapter = createGeneratedAdapter(
constructors.get(0), object);
return new SingleGeneratedAdapterObserver(generatedAdapter);
}
GeneratedAdapter[] adapters = new GeneratedAdapter[constructors.size()];
for (int i = 0; i < constructors.size(); i++) {
adapters[i] = createGeneratedAdapter(constructors.get(i), object);
}
return new CompositeGeneratedAdaptersObserver(adapters);
}
return new ReflectiveGenericLifecycleObserver(object);
}
Copy the code
1. The first case
The FullLifecycleObserver extends several abstract methods of the same name based on the Activity/Fragment class lifecycle callback methods, which can be seen as a more concrete event splitting for LifecycleEventObserver. This allows users to handle only the lifecycle events they care about, which is typically used on compilation platforms above Java 8
interface FullLifecycleObserver extends LifecycleObserver {
void onCreate(LifecycleOwner owner);
void onStart(LifecycleOwner owner);
void onResume(LifecycleOwner owner);
void onPause(LifecycleOwner owner);
void onStop(LifecycleOwner owner);
void onDestroy(LifecycleOwner owner);
}
Copy the code
FullLifecycleObserverAdapter LifecycleEventObserver interface is achieved, is used to receive Lifecycle events life cycle state change, Event forwarding is performed for the two construction parameters FullLifecycleObserver and LifecycleEventObserver
class FullLifecycleObserverAdapter implements LifecycleEventObserver {
private final FullLifecycleObserver mFullLifecycleObserver;
private final LifecycleEventObserver mLifecycleEventObserver;
FullLifecycleObserverAdapter(FullLifecycleObserver fullLifecycleObserver,
LifecycleEventObserver lifecycleEventObserver) {
mFullLifecycleObserver = fullLifecycleObserver;
mLifecycleEventObserver = lifecycleEventObserver;
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
switch (event) {
case ON_CREATE:
mFullLifecycleObserver.onCreate(source);
break;
case ON_START:
mFullLifecycleObserver.onStart(source);
break;
case ON_RESUME:
mFullLifecycleObserver.onResume(source);
break;
case ON_PAUSE:
mFullLifecycleObserver.onPause(source);
break;
case ON_STOP:
mFullLifecycleObserver.onStop(source);
break;
case ON_DESTROY:
mFullLifecycleObserver.onDestroy(source);
break;
case ON_ANY:
throw new IllegalArgumentException("ON_ANY must not been send by anybody");
}
if(mLifecycleEventObserver ! =null) { mLifecycleEventObserver.onStateChanged(source, event); }}}Copy the code
2. The second case
For the second case of reflection operation, its logic will be relatively complex, need to conduct a series of type judgment, type caching, reflection calls and other operations, here mainly look at ClassesInfoCache for the use of OnLifecycleEvent annotation method is how to limit
As we know, reflection on the Java platform is an inefficient and performance-consuming behavior. To avoid having to parse a class object containing the OnLifecycleEvent annotation every time an event callback is required, So classes, methods, and so on are cached inside Lifecycling for later reuse. Lifecycling encapsulates this cache information and stores it inside ClassesInfoCache. In addition, there are strict limits on the type, order, and number of input parameters of an annotated method. After all, if the developer declares a String as an input parameter for the callback method, it will not make sense
ClassesInfoCache internally determines whether the specified class object contains a method annotated using OnLifecycleEvent and caches the result in mHasLifecycleMethods. Cache information will be retrieved according to createInfo(Klass, Methods)
// Determine if the specified class object contains methods annotated with OnLifecycleEvent
boolean hasLifecycleMethods(Class
klass) {
Boolean hasLifecycleMethods = mHasLifecycleMethods.get(klass);
if(hasLifecycleMethods ! =null) {
// Return the cached value if there is a local cache
return hasLifecycleMethods;
}
// There are no cached values locally, so the following logic is used to determine by reflection whether klass contains annotations using OnLifecycleEvent
// Get all the methods klass contains
Method[] methods = getDeclaredMethods(klass);
for (Method method : methods) {
OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class);
if(annotation ! =null) {
// Optimization for reflection, we know that this method is called
// when there is no generated adapter. But there are methods with @OnLifecycleEvent
// so we know that will use ReflectiveGenericLifecycleObserver,
// so we createInfo in advance.
// CreateInfo always initialize mHasLifecycleMethods for a class, so we don't do it
// here.
createInfo(klass, methods);
return true;
}
}
mHasLifecycleMethods.put(klass, false);
return false;
}
Copy the code
The createInfo method imposes restrictions on the type, order, and number of input parameters of the annotated method, and will throw an exception at runtime if it does not
// The following three integer values are used to mark the number of input parameters of the annotated method
// Does not contain input arguments
private static final int CALL_TYPE_NO_ARG = 0;
// Contains an input parameter
private static final int CALL_TYPE_PROVIDER = 1;
// Contains two input parameters
private static final int CALL_TYPE_PROVIDER_WITH_EVENT = 2;
private CallbackInfo createInfo(Class<? > klass,@Nullable Method[] declaredMethods) { Class<? > superclass = klass.getSuperclass(); Map<MethodReference, Lifecycle.Event> handlerToEvent =new HashMap<>();
if(superclass ! =null) {
CallbackInfo superInfo = getInfo(superclass);
if(superInfo ! =null) { handlerToEvent.putAll(superInfo.mHandlerToEvent); } } Class<? >[] interfaces = klass.getInterfaces();for(Class<? > intrfc : interfaces) {for(Map.Entry<MethodReference, Lifecycle.Event> entry : getInfo( intrfc).mHandlerToEvent.entrySet()) { verifyAndPutHandler(handlerToEvent, entry.getKey(), entry.getValue(), klass); } } Method[] methods = declaredMethods ! =null ? declaredMethods : getDeclaredMethods(klass);
boolean hasLifecycleMethods = false;
for (Method method : methods) {
// Find a way to include the OnLifecycleEvent annotation
OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class);
if (annotation == null) {
continue;
}
hasLifecycleMethods = true;
// All the following logic looks like this:
//1. Obtain the number and type of params corresponding to method
//2. If the number of parameters is 0, callType = CALL_TYPE_NO_ARG, method does not contain parameters
//3. If the number of arguments is greater than 0, the first argument must be an object of type LifecycleOwner, otherwise an exception will be thrown
If the number of parameters is 1, callType = CALL_TYPE_PROVIDER
// if the number of parameters is 2, the annotation value annotation must be Lifecycle.event.on_any
// And the second argument must be an object of type Lifecycle.Event, otherwise an exception will be thrown
CallType = CALL_TYPE_PROVIDER_WITH_EVENT if all conditions are met
If the number of parameters is greater than 2, an exception will be thrown, that is, method must contain at most two parameters, and the parameter type and the parameter order are restrictedClass<? >[] params = method.getParameterTypes();int callType = CALL_TYPE_NO_ARG;
if (params.length > 0) {
callType = CALL_TYPE_PROVIDER;
if(! params[0].isAssignableFrom(LifecycleOwner.class)) {
throw new IllegalArgumentException(
"invalid parameter type. Must be one and instanceof LifecycleOwner");
}
}
Lifecycle.Event event = annotation.value();
if (params.length > 1) {
callType = CALL_TYPE_PROVIDER_WITH_EVENT;
if(! params[1].isAssignableFrom(Lifecycle.Event.class)) {
throw new IllegalArgumentException(
"invalid parameter type. second arg must be an event");
}
if(event ! = Lifecycle.Event.ON_ANY) {throw new IllegalArgumentException(
"Second arg is supported only for ON_ANY value"); }}if (params.length > 2) {
throw new IllegalArgumentException("cannot have more than 2 params");
}
MethodReference methodReference = new MethodReference(callType, method);
verifyAndPutHandler(handlerToEvent, methodReference, event, klass);
}
CallbackInfo info = new CallbackInfo(handlerToEvent);
mCallbackMap.put(klass, info);
mHasLifecycleMethods.put(klass, hasLifecycleMethods);
return info;
}
Copy the code
The final reflection call is then made in the invokeCallback() method inside the MethodReference class. MethodReference is used to cache a Method with an OnLifecycleEvent annotation and the number of incoming parameters of that Method. Lifecycle.Event notification is made via the invokeCallback() method
static 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, Object target) {
//noinspection TryWithIdenticalCatches
// Pass specific parameters based on the number of inputs and perform reflection callbacks
// Therefore, the annotation method with OnLifecycleEvent has fixed requirements on the number of input parameters, type of input parameters, and declaration order of input parameters
// An exception will be thrown as reflection fails when the requirement is not met
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 newRuntimeException(e); }}// omit irrelevant methods...}Copy the code
Six, summarized
Lifecycle has been described above and will be summarized here
- We use it everyday
androidx.appcompat.app.AppCompatActivity
å’Œandroidx.fragment.app.Fragment
Both implement the LifecycleOwner interface, whichgetLifecycle()
Method returns all LifecycleRegistry androidx.core.app.ComponentActivity
By default, LifecycleRegistry has a ReportFragment mounted without a UI. The ReportFragment will retrieve Activity lifecycle events in different ways depending on the system version number of the user’s phone, and eventually call LifecycleRegistryhandleLifecycleEvent(Lifecycle.Event)
Method passes Lifecycle.Event. LifecycleRegistry now gets Lifecycle.Event. The purpose of ReportFragment is to completely mask system version differences so that external callback notifications can be obtained in a unified wayandroidx.fragment.app.Fragment
LifecycleRegistry will be called directly internallyhandleLifecycleEvent(Lifecycle.Event)
Method completes event notification- LifecycleRegistry will be external
addObserver
LifecycleObserver objects passed in are wrapped as LifecycleEventObserver objects, shielding external LifecycleObserver differences (interfaces, annotations) - LifecycleRegistry works by directly calling the LifecycleEventObserver object
onStateChanged
Method to complete the final event callback, and the process is complete