For those who are not familiar with the LifeCycle component, read this article:
A detailed explanation of Jetpack’s LifeCycle component
Learning problems
-
How does LifeCycle listen to changes in the Activity/Fragment LifeCycle?
-
How does LifeCycle distribute events that change during the LifeCycle to observers?
This article directory
One or four important classes
(a) Lifecycle
Lifecycle is an abstract class. It defines two enumerations internally: Event the type of Event to be distributed, and State the State of the host.
1.Event
public enum Event {
// The onCreate method corresponding to the host (the class that implements LifecycleOwner)
ON_CREATE,
// The onStart method corresponding to the host (the class that implements LifecycleOwner)
ON_START,
// The onResume method corresponding to the host (the class that implements LifecycleOwner)
ON_RESUME,
// The onPause method corresponding to the host (the class that implements LifecycleOwner)
ON_PAUSE,
// The onStop method corresponding to the host (the class that implements LifecycleOwner)
ON_STOP,
// The onDestroy method corresponding to the host (the class implementing LifecycleOwner)
ON_DESTROY,
// Can match all life cycle events of the host
ON_ANY
}
Copy the code
Timing of distribution of each lifecycle event:
ON_CREATE, ON_START, and ON_RESUME: These three lifecycle events are distributed after the execution of the host’s corresponding lifecycle method has completed.
ON_PAUSE, ON_STOP, and ON_DESTROY: These three lifecycle events are distributed before the host’s corresponding lifecycle method is called.
2.State
public enum State {
// Destroyed state. In the case of an Activity, the host reaches this state before calling back the Activity's onDestroy method.
DESTROYED,
// Initialized state. A state before the callback to the onCreate method.
INITIALIZED,
// The state has been created. There are two ways to be in this state:
//1. After the host's onCreate method is executed
//2. Before the host's onStop method is called
CREATED,
// Visible state. There are two ways to be in this state:
//1. After the host's onStart method is executed
//2. Before the host's onPause method is called
STARTED,
// Focus (interactive state). The host is in this state after executing the onResume method.
RESUMED;
public boolean isAtLeast(@NonNull State state) {
return compareTo(state) >= 0; }}Copy the code
3. Mapping between Event and State
(2) LifecycleRegistry
It is the only implementation class for Lifecycle. It is primarily used to register observers (LifecycleObservers) and distribute host state to them (multiple observers can be handled).
(3) LifecycleOwner
To declare that it is a host for lifecycle events, both activities and fragments implement this interface. There is only one getLifecycle method internally.
public interface LifecycleOwner {
@NonNull
Lifecycle getLifecycle(a);
}
Copy the code
(4) LifecycleObserver
Used to define an observer.
The relationship between the four classes
Description:
- Activities/fragments both implement the LifecycleOwner interface by default;
- LifecycleRegistry is Lifecycle’s only implementation class;
- There are three ways to implement an Observer:
- LifecycleObserver is annotated with @onlifecyCleEvent
- DefaultLifecycleObserver hosts all life cycle events
- LifecycleEventObserver encapsulates host Lifecycle events as lifecyc.event
- Pass in an Activity/Fragment
getLifecycle()
Method to get a LifecycleRegistry object; - By calling the LifecycleRegistry object
addObserver()
Add an observer (which can be implemented in any of the three ways).
3. How to implement LifyCycle in fragments
LifecycleRegistry is used to distribute events within each lifecycle method of the Fragment.
public class Fragment implements LifecycleOwner {
LifecycleRegistry mLifecycleRegistry;
void performCreate(Bundle savedInstanceState) {
onCreate(savedInstanceState);
// The ON_CREATE event is distributed after the onCreate method is executed
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
}
void performStart(a) {
onStart();
// The ON_START event is distributed after the onStart method is executed
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
}
void performResume(a) {
onResume();
// The ON_RESUME event is distributed after the onResume method has been executed
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
}
void performPause(a) {
// The ON_PAUSE event is distributed before the execution of the onPause method
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
onPause();
}
void performStop(a) {
// The ON_STOP event is distributed before the execution of the onStop method
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
onStop();
}
void performDestroy(a) {
// The ON_DESTROY event is distributed before the execution of the onDestroy methodmLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY); onDestroy(); }}Copy the code
4. How to implement LifyCycle for Activity
An Activity implementing Lifecycle requires adding a Fragment to the Activity using the ReportFragment. The ReportFragment does not have any pages and is only responsible for distributing events using LifecycleRegistry when the lifecycle changes.
The ReportFragment is needed to accommodate scenarios that are not inherited from AppCompactActivity, and also to support our custom LifecycleOwner scenarios.
(a) ComponentActivity source analysis
The following is the source code for ComponentActivity, in the onCreate method to add a fragment inside the Activity.
public class ComponentActivity extends Activity implements LifecycleOwner {
private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
@SuppressLint("RestrictedApi")
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add a fragment
ReportFragment.injectIfNeededIn(this); }}Copy the code
Add an inheritance to the Activity:
(2) Source analysis of ReportFragment
Let’s take a look at the ReportFragment source code. InjectIfNeededIn is the main method in the ReportFragment.
public class ReportFragment extends Fragment {...public static void injectIfNeededIn(Activity activity) {
/ / 1. If the API > = 29, registered ActivityLifecycleCallbacks
if (Build.VERSION.SDK_INT >= 29) {
activity.registerActivityLifecycleCallbacks(
new LifecycleCallbacks());
}
//2. Add ReportFragment to the Activity
android.app.FragmentManager manager = activity.getFragmentManager();
if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
manager.beginTransaction().add(newReportFragment(), REPORT_FRAGMENT_TAG).commit(); manager.executePendingTransactions(); }}...Copy the code
The injectIfNeededIn method does two things:
1. Determine the current API Level and select the time and mode to listen for the Activity lifecycle based on the API Level
(1) API Level >= 29
If greater than or equal to 29, will register a ActivityLifecycleCallbacks,
if (Build.VERSION.SDK_INT >= 29) {
activity.registerActivityLifecycleCallbacks(new LifecycleCallbacks());
}
Copy the code
ActivityLifecycleCallbacks is the Application of an internal interface.
public interface ActivityLifecycleCallbacks {
void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState);
void onActivityStarted(@NonNull Activity activity);
void onActivityResumed(@NonNull Activity activity);
void onActivityPaused(@NonNull Activity activity);
void onActivityStopped(@NonNull Activity activity);
void onActivityDestroyed(@NonNull Activity activity);
}
Copy the code
To the Activity’s onResume () life cycle as an example, if we register the ActivityLifecycleCallbacks, The Android system will first callback ActivityLifecycleCallbacks onActivityResumed method, then the implementation of the Android itself onResume () method.
Using this feature, we can register a custom ActivityLifecycleCallbacks, add custom on the ActivityLifecycleCallbacks distribution, the logic of life cycle events to notify observers:
public class ReportFragment extends Fragment {
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(newReportFragment(), REPORT_FRAGMENT_TAG).commit(); manager.executePendingTransactions(); }}@SuppressWarnings("deprecation")
static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) {...if (activity instanceof LifecycleOwner) {
Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
if (lifecycle instanceof LifecycleRegistry) {
// LifecycleRegistry is ultimately used to handle event distribution((LifecycleRegistry) lifecycle).handleLifecycleEvent(event); }}}/ / custom ActivityLifecycleCallbacks to handle life cycle events distribution, notify the observer
static class LifecycleCallbacks implements Application.ActivityLifecycleCallbacks {...@Override
public void onActivityPostCreated(@NonNull Activity activity,
@Nullable Bundle savedInstanceState) {
// Distribute the ON_CREATE event
dispatch(activity, Lifecycle.Event.ON_CREATE);
}
@Override
public void onActivityPostStarted(@NonNull Activity activity) {
// Distribute the ON_START event
dispatch(activity, Lifecycle.Event.ON_START);
}
@Override
public void onActivityPostResumed(@NonNull Activity activity) {
// Distribute the ON_RESUME event
dispatch(activity, Lifecycle.Event.ON_RESUME);
}
@Override
public void onActivityPrePaused(@NonNull Activity activity) {
// Distribute the ON_PAUSE event
dispatch(activity, Lifecycle.Event.ON_PAUSE);
}
@Override
public void onActivityPreStopped(@NonNull Activity activity) {
// Distribute the ON_STOP event
dispatch(activity, Lifecycle.Event.ON_STOP);
}
@Override
public void onActivityPreDestroyed(@NonNull Activity activity) {
// Distribute the ON_DESTROY eventdispatch(activity, Lifecycle.Event.ON_DESTROY); }... }}Copy the code
(2) API Level < 29
If the API is less than 29, the implementation is the same as the Fragment implementation, using LifecycleRegistry to distribute the corresponding Lifecycle.Event events to each observer within each Lifecycle method:
public class ReportFragment extends Fragment {
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(newReportFragment(), REPORT_FRAGMENT_TAG).commit(); manager.executePendingTransactions(); }}@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 onResume(a) {
super.onResume();
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);
}
private void dispatch(@NonNull Lifecycle.Event event) {
// Check the API here to avoid duplicating events
if (Build.VERSION.SDK_INT < 29) { dispatch(getActivity(), event); }}}Copy the code
InjectIfNeededIn creates a ReportFragment and adds it to the Activity
public class ReportFragment extends Fragment {
public static void injectIfNeededIn(Activity activity) {...// Add a ReportFragment to the Activity
android.app.FragmentManager manager = activity.getFragmentManager();
if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
manager.beginTransaction().add(newReportFragment(), REPORT_FRAGMENT_TAG).commit(); manager.executePendingTransactions(); }}}Copy the code
Five, LifecycleRegistry source code analysis
In the previous analysis, we saw how activities/fragments implement LifeCycle. LifecycleRegistry ultimately handles the distribution of LifeCycle events. Therefore, We have a comparative look at the inner workings of LifecycleRegistry.
(a) addObserver() source code analysis
LifeCycle is implemented through the observer pattern. Adding an observer is done by calling the addObserver() method:
getLifecycle().addObserver(observer);
Copy the code
Let’s look at the complete addObserver() method:
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
Here’s a line by line analysis:
1. First determine the initialization status of the newly added Observer
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
Copy the code
As long as the current host state is not DESTROYED, its initial state is INITIALIZED.
2. Wrap the Observer as ObserverWithState
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
Copy the code
ObserverWithState represents an Observer with state. This class will be examined in more detail later.
3. Add the Observer to the collection
ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
if(previous ! =null) {
return;
}
Copy the code
Add ObserverWithState to the collection using the putIfAbsent() method. If you have added it before, the putIfAbsent() method will return the ObserverWithState directly. In this case, the program will return directly.
4. Use a while loop to align the observer and host states
// First calculate the state the observer should be in
State targetState = calculateTargetState(observer);
// Compare the observer's state to the host's current state using the compareTo method. If the state is less than 0, the two states are not aligned
while ((statefulObserver.mState.compareTo(targetState) < 0
&& mObserverMap.contains(observer))) {
pushParentState(statefulObserver.mState);
// Perform an event distribution
statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
popParentState();
// The next state that the observer should be in is calculated, and the observer state will be compared to it in the next loop until the states align and exit the loop
targetState = calculateTargetState(observer);
}
Copy the code
Using the logic of the while loop, we can conclude:
Registered observers in any lifecycle method of an Activity/Fragment receive full lifecycle events.
For example, we register observers in the onResume() method:
- While first loop: distributes on_Create event, observer state INITIALIZED -> CREATED
- While second loop: distribute on_Start event, observer status CREATED -> STARTED
- While third loop: distribute on_Resume event, observer state STARTED -> RESUMED
However, it is best to register in the onCreate method.
Refer to the article for comparing two enumeration values using compareTo:
Java enumeration comparison
(2) handleLifecycleEvent() source analysis
The handleLifecycleEvent() method is primarily responsible for the corresponding event distribution when the host lifecycle changes.
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
State next = getStateAfter(event);
moveToState(next);
}
Copy the code
1. First, according to the event that needs to be distributed, what state is the host in
Assuming that the ON_START event is being distributed, the host is currently in the STARTED state according to the getStateAfter() method.
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;
}
Copy the code
2. Set the current host state according to the host state obtained in step 1 and notify the observer
private void moveToState(State next) {
if (mState == next) {
return;
}
// Set the current statemState = next; .// Notify the observer
sync();
}
Copy the code
Let’s look at the sync method:
private void sync(a) {
while(! isSynced()) {// If the current state of the host is less than the state of the first observer added to the mObserverMap set
// The host may fall back to the RESUMED state. For example, if the host is RESUMED, onPause falls back to the STARTED state
// backwardPass is called to distribute an on_PAUSE event to each observer in the collection and synchronize its state.
if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
backwardPass(lifecycleOwner);
}
// If the current state of the host is greater than the state of the first observer added to the mObserverMap set
// The host may have advanced to a RESUMED state. For example, if the host is in the STARTED state, the host RESUMED to a RESUMED state
// Call forwardPass to distribute an on_Resume event to each observer in the collection and synchronize its state.
Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
if(! mNewEventOccurred && newest ! =null
&& mState.compareTo(newest.getValue().mState) > 0) {
forwardPass(lifecycleOwner);
}
}
mNewEventOccurred = false;
}
Copy the code
(3) Analysis of ObserverWithState source code
ObserverWithState is the inner class in LifecycleRegistry that holds the observer and its state.
static class ObserverWithState {
State mState;
LifecycleEventObserver mLifecycleObserver;
// ADAPTS the incoming LifecycleObserver to LifecycleEventObserver in order to unify the distribution of events.
// In the previous article, we explained that there are three types of implementation observer, each of which receives a different type of event. If you do not uniformly distribute the event, it can become cumbersome
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);
// Perform event distributionmLifecycleObserver.onStateChanged(owner, event); mState = newState; }}Copy the code
6. Reference materials
Official Google Jetpack documentation
Moocs: Learn Jetpack from an architect
The Android Jetpack App Guide by Ye Kun