The beginning is nonsense.
Defines an object for the Android life cycle. The Fragment and FragmentActivity classes implement the LifecycleOwner interface and can access the lifecycle through the getLifecycle() method. We can also implement LifecycleOwner in our own class.
// When the return of the relevant method of LifecycleOwner is distributed after such an event.ON_CREATE, Lifecycle.Event.ON_START, Lifecycle// Dispatches the related methods LifecycleOwner calls before such an event. For example, Lifecycle.event. ON_START will be sent onStart return and Lifecycle.event. ON_STOP will be sent onStop will be called. This gives you some assurance that the master in his country is not present.ON_PAUSE, Lifecycle.Event.ON_STOP, LifecycleCopy the code
If you are using the Java 8 language, then use DefaultLifecycleObserver to observe the events. Need to be “androidx. Lifecycle: common – java8: < version >” added to your build. Gradle file.
class TestObserver implements DefaultLifecycleObserver {
@Override
public void onCreate(LifecycleOwner owner) {
// your code}}Copy the code
If you use the Java 7 language, observe life cycle events using annotations. Once Java 8 becomes mainstream on Android, annotations will be deprecated, so DefaultLifecycleObserver must be biased towards annotations.
class TestObserver implements LifecycleObserver {
@OnLifecycleEvent(ON_STOP)
void onStopped(a) {}}Copy the code
The observation method can receive zero or one parameter. If used, the first parameter must be of type LifecycleOwner. The annotated method Lifecycle.event. ON_ANY can receive a second parameter, which must be of type Lifecycle.
class TestObserver implements LifecycleObserver {
@OnLifecycleEvent(ON_CREATE)
void onCreated(LifecycleOwner source) {}
@OnLifecycleEvent(ON_ANY)
void onAny(LifecycleOwner source, Event event) {}}Copy the code
Providing these additional parameters allows you to easily observe multiple vendors and events without having to manually track them.
So what can I do
At this point, we should think of something that is not often overlooked in development, but is rarely used
In Umo statistics, we often insert umO statistics on page flow in BaseActivity, onStart(), onResume(), onPause(), onStop(), etc. However, the downside here is that our business is coupled to public components.
Here comes the dry stuff
The solution to this problem is to implement LifecycleObserver, declare the cycle method with the identifier, and just say addObserver(this), You can associate the Activity or Fragment declaration cycle method with the Observer method we defined. Through the declaration cycle method of aware activities or fragments, the friend count is implemented, and the business as a whole is separated from BaseActivity, making the common components more concise.
Of course, this is a simple application for Lifecycle and there are other ways to use Lifecycle that will need to be explored.
Source code analysis
Lifecycle UML
The best way to understand something is to read it.
As we can see from the UML class diagram above, Lifecycle is not very much. But how can it be so powerful.
ComponentActivity
& ReportFragment
Lifecycle people who don’t know Lifecycle should know that this is going to provide a Lifecycle monitoring class, so since Lifecycle has something to do with activities, we can look up through the AppCompatActivity class, We can see that the ComponentActivity class implements the LifecycleOwner interface and returns an mLifecycleRegistry
// The ComponentActivity class initializes by creating a LifecycleRegistry and passing itself in
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
// LifecycleOwner interface which provides a getLifecycle() method
@Override
public Lifecycle getLifecycle(a){
return mLifecycleRegistry;
}
Copy the code
The ComponentActivity constructor ADAPTS to different platform versions.
public ComponentActivity(a) {
Lifecycle lifecycle = getLifecycle();
//noinspection ConstantConditions
if (lifecycle == null) {
throw new IllegalStateException("getLifecycle() returned null in ComponentActivity's "
+ "constructor. Please make sure you are lazily constructing your Lifecycle "
+ "in the first call to getLifecycle() rather than relying on field "
+ "initialization.");
}
if (Build.VERSION.SDK_INT >= 19) {
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_STOP) {
Window window = getWindow();
finalView decor = window ! =null ? window.peekDecorView() : null;
if(decor ! =null) { decor.cancelPendingInputEvents(); }}}}); } getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
if(! isChangingConfigurations()) { getViewModelStore().clear(); }}}});if (19 <= SDK_INT && SDK_INT <= 23) {
getLifecycle().addObserver(new ImmLeaksCleaner(this)); }}Copy the code
LifecycleRegister: addObserver() : addObserver() : addObserver() Scrolling through the class structure, LifecycleRegister is a subclass of Lifecycle, and everything related to the declaration cycle is related to this class.
Instead of looking at LifecycleRegister, look at the CompontentActivity class. Since it’s an Activity, there must be a creation process. Looking back at the onCreate() method, we can observe something interesting:
/ * * * {@inheritDoc}
*
* If your ComponentActivity is annotated with {@link ContentView}, this will
* call {@link #setContentView(int)} for you.
*/
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSavedStateRegistryController.performRestore(savedInstanceState);
ReportFragment.injectIfNeededIn(this);
if(mContentLayoutId ! =0) { setContentView(mContentLayoutId); }}Copy the code
ReportFragment. InjectIfNeededIn (this) yi??????????????? Who are you? What are you doing here.
Don’t panic. Go inside.
ReportFragment
public static void injectIfNeededIn(Activity activity) {
// ProcessLifecycleOwner should always correctly work and some activities may not extend
// FragmentActivity from support lib, so we use framework fragments for activities
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
Yi ???? Why did I add a Fragment to my Activity and look through the code? We didn’t see any layout. You were empty, 😱😱😱.
In terms of the Fragment lifecycle, let’s move on
dispatch()
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
dispatchCreate(mProcessListener);
dispatch(Lifecycle.Event.ON_CREATE);
}
@Override
public void onStart(a) {
super.onStart();
dispatchStart(mProcessListener);
dispatch(Lifecycle.Event.ON_START);
}
@Override
public void onResume(a) {
super.onResume();
dispatchResume(mProcessListener);
dispatch(Lifecycle.Event.ON_RESUME);
}
@Override
public void onPause(a) {
super.onPause();
dispatch(Lifecycle.Event.ON_PAUSE);
}
@Override
public void onStop(a) {
super.onStop();
dispatch(Lifecycle.Event.ON_STOP);
}
@Override
public void onDestroy(a) {
super.onDestroy();
dispatch(Lifecycle.Event.ON_DESTROY);
// just want to be sure that we won't leak reference to an activity
mProcessListener = null;
}
Copy the code
Lifecycle.Event Event (Dispatch) and pass in parameters that match the Lifecycle of the Activity. So let’s look at it.
handleLifecycleEvent()
private void dispatch(Lifecycle.Event event) {
Activity activity = getActivity();
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
It’s two decisions, but it doesn’t matter, because that’s what the system is doing for us, but anyway, they’re calling the handleLifecycleEvent method on their team, and they’re fooling no, they’re not doing anything here, they’re just running away.
You run, I chase!
LifecycleRegister
/**
* Sets the current state and notifies the observers.
* <p>
* Note that if the {@code currentState} is the same state as the last call to this method,
* calling this method has no effect.
*
* @param event The event that was received
*/
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
Two methods. Let’s translate the comments
Sets the current state and notifies the observer
Note that if the current state is the same as when the last method was called, this call is invalid
getStateAfter()
Now let’s look at the source code for the getStateAfter(event) method. Let’s take a look at what it does:
static State getStateAfter(Event event) {
switch (event) {
case ON_CREATE:
case ON_STOP:
return CREATED;
case ON_START:
case ON_PAUSE:
return STARTED;
case ON_RESUME:
return RESUMED;
case ON_DESTROY:
return DESTROYED;
case ON_ANY:
break;
}
throw new IllegalArgumentException("Unexpected event value " + event);
}
Copy the code
It is a static method that finds the next lifecycle State corresponding to the current Event by passing in the Event
There’s another method that we haven’t analyzed moveToState(State Next), and from the name of the function, we can see that this is a method that moves the State. What is that
if (mState == next) {
return;
}
Copy the code
If the current state is the same as the next (after operation) state, return directly. This also mirrors the comment.
sync()
To continue, the next state of the operation is recorded. We will see a sync() method instead of some criteria. ===> Status synchronization
/** * Custom list that keeps observers and can handle removals / additions during traversal. * * Invariant: at any moment of time for observer1 & observer2: * if addition_order(observer1) < addition_order(observer2), then * state(observer1) >= state(observer2), */
private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
new FastSafeIterableMap<>();
// happens only on the top of stack (never in reentrance),
// so it doesn't have to take in account parents
private void sync(a) {
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
There’s a new thing called mObserverMap and we’re looking for its type. We’re not looking at data structures here, but briefly, it’s a two-way linked list that provides a map for a buffer, and provides a structure that can iterate quickly.
Continue analyzing the source code
MState.com pareTo(mobServermap.eldest ().getValue().mstate) < 0 Takes the oldest state from the cached observer and compares it with the current state. If less than 0, the observer’s state is earlier than the current state. A backwardPass(lifecycleOwner) method is executed to revert the observer’s state back to its current state
MState.com pareTo(newest.getValue().mstate) > 0 is opposite to the above judgment, indicating that the status of the current observer is behind the current state, so let the status of the observer catch up with the current state, Perform forwardPass (lifecycleOwner)
Lifecycle State Sequence
By analyzing the forwardPass and backwardPass methods, we see that two more methods, downEvent and upEvent, are called internally, which we call the escalation event and the degradation event
private static Event downEvent(State state) {
switch (state) {
case INITIALIZED:
throw new IllegalArgumentException();
case CREATED:
return ON_DESTROY;
case STARTED:
return ON_STOP;
case RESUMED:
return ON_PAUSE;
case DESTROYED:
throw new IllegalArgumentException();
}
throw new IllegalArgumentException("Unexpected state value " + state);
}
private static Event upEvent(State state) {
switch (state) {
case INITIALIZED:
case DESTROYED:
return ON_CREATE;
case CREATED:
return ON_START;
case STARTED:
return ON_RESUME;
case RESUMED:
throw new IllegalArgumentException();
}
throw new IllegalArgumentException("Unexpected state value " + state);
}
Copy the code
Using the above two methods, we can conclude the sequential relationship between State and Event in Lifecycle as shown in the figure below
We can also see the relationship between state and event by reviewing the getStateAfter() method’s determination of events and states.
dispatchEvent
private void forwardPass(LifecycleOwner lifecycleOwner) {
Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
mObserverMap.iteratorWithAdditions();
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();
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
Here are the two ways to be late, and there’s nothing complicated here. Just find all the observers through the loop and distribute the event observer.dispatchEvent(lifecycleOwner, event)
void dispatchEvent(LifecycleOwner owner, Event event) {
State newState = getStateAfter(event);
mState = min(mState, newState);
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}
Copy the code
Hanged onStateChanged(owner, Event) another method comes to our attention onStateChanged(owner, Event), click on it again and find that it is an interface. Query can see that there are many implementation classes, confused? ????
But we need to focus only on ReflectiveGenericLifecycleObserver, want to know why? I also looked at the source code to sum up.
ReflectiveGenericLifecycleObserver
/**
* An internal implementation of {@link LifecycleObserver} that relies on reflection.
*/
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
Ah, mInfo. InvokeCallbacks (source, event, mWrapped); What is this? We’ve never seen this before. We’ve never seen the initialization and loading of this class, have we, 😨😨😨
Since it is a class, it must be created, so look at the constructor.
Wrapped, it’s been cached, Emmm, and I clicked on ClassesInfoCache to get it all wrapped.
And what’s wrapped? Through ClassesInfoCache and we can see tracking ReflectiveGenericLifecycleObserver, ClassesInfoCache caches LifecycleObserver class object, A LifecycleObserver ReflectiveGenericLifecycleObserver is passed down. From this we can conclude that the LifecycleObserver is our own self-defined observer.
What the system does for me is to use reflection technology to execute our method minfo. invokeCallback(Source Event, mWrapped) with our own annotations based on the current lifecycle state;
reflect invoke method
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 newRuntimeException(e); }}Copy the code
Remember the translation of Lifecycle’s annotations at the beginning of this article? The judgment here is based on the annotation annotation and the callback to the corresponding parameter method
At this point, it looks like we can’t go any further, and the execution of the code is over at this point.
But !!!!!!!!!!!!!!!!
We still have a big chunk left unanalyzed !!!!!!!!!!!!!!!!!!!!!!!!
addObserver()
We’ve talked a lot about how Lifecycle is handled and listens to our Lifecycle, that is, how Lifecycle is handled. So we haven’t said that before, from the observer ?????????
Ok, so let’s go ahead and look at the addObserver(LifecycleObserver) in the Lifecyclegister and this is the method that we need to call after we customize the observer
@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) {
return;
}
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
if (lifecycleOwner == null) {
// it is null we should be destroyed. Fallback quickly
return;
}
booleanisReentrance = 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
Haha, looks like the code is not a lot of ya !!!! Oh, innocent you! But that’s it
We’re going to count them line by line here
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED; Come up to initialize a well, a state of the INITIALIZED state, ha, ha, ha, good man.
We then create an ObserverWithState, which is a stateful observer, as we can tell from the name. The two parameters are the observer we passed in and the state we just created. This is a decorator pattern, which is a scheme to add a new property to the original object without changing the original data structure.
And then I put that observer and the observer with the state into the Map that I had already created, which is the mObserverMap and I returned something that, when I read it, matched up with Lifecycle’s annotation again.
Then, calculate the current state of the Activity or Fragment and determine that if the current observer is behind the state of the Activity or Fragment, execute the dispatchEvent() method immediately to execute the callback.
conclusion
After reading the source code, Lifecycle’s technology is very simple, just reflection, observer, decorator, and it does all three things very well.
To sum up, we analyze the source code from two aspects
-
addObserver()
This method is the most direct content for users. When we create an Observer, we will pass in the Observer defined by ourselves through the way of Add, so from this breakthrough we enter the source code analysis to observe
- To add
Observer
An initial state (decorator pattern, wrapper data) - Store data in the local cache (
mObserverMap
) - Make an immediate state judgment to determine whether to handle life cycle changes
- To add
-
ReportFragment
Attached to the Activity, it is used to sense changes in the Activity’s life cycle and to separate the business from the Activity. The lifecycle event is dispatched to all of its observers to process the message handleLifecycleEvent by executing the Dispatch () method through the life-aware lifecycle change
-
reflection
It’s kind of abstract, there’s nothing there that’s obviously relevant to us, and as long as you’re familiar with reflection, then you can understand what it does.
-
sync()
This method is used to quickly synchronize the state of the observer with activities and fragments, and is intended to allow the observer to execute all of its observed data. Two methods, forwardPass() and backwardPass(), are how it works.