Lifecycle profile
LifeCycle components are used to distribute the life of objects with a LifeCycle, such as activities and fragments, so that other objects can change their LifeCycle.
It is the basis for other components of JetPack, such as LiveData in JetPack, which allows an Activity to be unobserved in the background without calling back events or being destroyed
Why life distribution
We often encounter the following scenarios when using components that have the Android life cycle
1. You need to notify a member variable to initialize in the Activity’s onCreate() method (for example, Presenter,AudioManager, etc.)
2. The onStop() and onDestroy() methods of the Activity inform member variables to unbind resources to prevent memory leaks, etc
LifeCycle in the chaotic years before LifeCycle appeared
1. Manually callback the observer lifecycle event in the Activity/Fragment
Before LifeCycle components appear, there are two ways to approach this scenario. One is to manually call back the corresponding methods of member variables throughout the LifeCycle of an Activity, as follows:
MyPresenter {
fun start(){
//doSomething
}
fun stop(){
//doSomething
}
}
class MainActivity : AppCompatActivity() {
private val mPresenter = MyPresenter()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mPresenter.start()
}
override fun onDestroy() {
super.onDestroy()
mPresenter.stop()
}
}
Copy the code
While this approach meets the needs of our own page distribution life cycle, it is often possible to forget to call, resulting in bugs.
And when an Activity is a third-party page, it cannot be distributed in this way for its lifecycle.
2, Application. ActivityLifecycleCallbacks
In the Lifecycle, the Android system provides Application. ActivityLifecycleCallbacks interface allows us to perceive this Application within all the change of the Activity Lifecycle, specific usage is as follows:
class MyPresenter: Application.ActivityLifecycleCallbacks {
/** * Called when the Activity calls [super.onCreate()][Activity.onCreate]. */
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
// dosomething
}
/** * Called when the Activity calls [super.onDestroy()][Activity.onDestroy]. */
override fun onActivityDestroyed(activity: Activity) {
// dosomething
}
/** * Called when the Activity calls [super.onPause()][Activity.onPause]. */
override fun onActivityPaused(activity: Activity){}/** * Called when the Activity calls [super.onStart()][Activity.onStart]. */
override fun onActivityStarted(activity: Activity){}/** * Called when the Activity calls * [super.onSaveInstanceState()][Activity.onSaveInstanceState]. */
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle){}/** * Called when the Activity calls [super.onStop()][Activity.onStop]. */
override fun onActivityStopped(activity: Activity){}/** * Called when the Activity calls [super.onResume()][Activity.onResume]. */
override fun onActivityResumed(activity: Activity){}}class MainActivity : AppCompatActivity(a){
private val mPresenter = MyPresenter()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Notice that this is the application method
application.registerActivityLifecycleCallbacks(mPresenter)
// The API is greater than or equal to 29
// registerActivityLifecycleCallbacks(mPresenter)
}
override fun onDestroy() {
super.onDestroy()
// No need to use, need to deregister
application.unregisterActivityLifecycleCallbacks(mPresenter)
}
}
Copy the code
After registering in this way, we can receive callbacks as the Activity lifecycle changes and execute the logic accordingly. Because it is a synchronous callback, we should be careful not to perform time-consuming operations in the callback method to prevent stuttering.
Because it is registered with an Application, an mPresenter object can listen for all Activity lifecycle callbacks from an Application.
In the SDK version > = 29, the Activity also provides its own registerActivityLifecycleCallbacks method, call the Activity this method registered observer will only receive Activity life cycle events callback.
Application. The advantages of ActivityLifecycleCallbacks:
By defining Application. ActivityLifecycleCallbacks interface shielding the differences between the observer. Events are also distributed in the Activity’s various life callback methods, essentially ensuring that each observer receives the event as the life cycle changes. It can be used to listen for both our own Activity life events and third-party Activity events.
Application. ActivityLifecycleCallbacks shortcomings:
With Application ActivityLifecycleCallbacks, solve the problem of the distribution of the Activity life cycle, but it is only applicable to the Activity life cycle of the distribution, And Android objects with a life cycle are not just activities (such as Services, fragments).
So Google has launched JetPack’s LifeCycle component, our star of the day
Overview of common classes for Lifecycle components
As you can see from the Lifecycle class diagram above, the Lifecycle component consists of LifecycleOwner,Lifecycle and LifecycleObserver.
-
LifecycleObserver Interface (LifecycleObserver) This is an empty interface that serves primarily as a markup. Dependent annotation methods can be registered with the addObserver(@nonnull LifecycleObserver Observer) method of the LifeCycle class and once registered will receive LifeCycleOwner distribution LifeCycle events. Its common sub-interfaces are LifecycleEventObserver and FullLifecycleObserver
-
LifecycleOwner interface (Lifecycle holder) the interface that Lifecycle objects such as activities and fragments need to implement. This interface has only one method, Lifecycle getLifecycle(), which provides Lifecycle objects, Lifecycle is required to notify the LifecycleObserver when its Lifecycle changes
-
Lifecycle is an abstract class that adds methods to remove the LifeCycleObserver interface and documents the current Lifecycle state
-
State (the State of the current lifecycle) is an enumerated class that represents various states of the lifecycle. There are DESTROYED, INITIALIZED, CREATED, STARTED, and RESUMED
-
Event(current lifecycle change events) is an enumeration class that represents the events associated with lifecycle changes. The options are ON_CREATE,ON_START,ON_RESUME,ON_PAUSE,ON_STOP,ON_DESTROY, and ON_ANY
LifecycleRegistry main source code parsing
LifecycleRegister LifecycleRegister is an implementation class for Lifecycle, implementing the logic and Lifecycle state management to add and remove LifecycleObserver, And the ability to notify the LifecycleObserver of changes to the LifecycleOwner’s life cycle. The LifecycleRegister class greatly simplifies the cost of using LifecyclerOwner for developers. Enables activities and fragments not to interact directly with the LifecycleObserver. Simply call the handleLifecycleEvent(@nonnull Lifecycle.Event Event) method of LifeCycleRegister when the Lifecycle changes.
Let’s look at its constructor:
public LifecycleRegistry(@NonNull LifecycleOwner provider) {
// Hold a weak reference to the LifeCycleOwner object to prevent LifeCycleRegistery from being held by a long-life object
// Cause LifeCycleOwner memory leak
mLifecycleOwner = new WeakReference<>(provider);
mState = INITIALIZED;
}
Copy the code
The constructor is simple; it simply saves the LifecycleOwner object passed in and sets the current state to INITIALIZED
Let’s look at how it adds observers
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
// Wrap LifecycleObserver and its state as an ObserverWithState object
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
// Indicates that the statefulObserver has been added
if(previous ! =null) {
return;
}
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
//lifecycleOwner is null, indicating that lifecycleOwner has been reclaimed, so no need to observe, return
if (lifecycleOwner == null) {
// it is null we should be destroyed. Fallback quickly
return; } boolean isReentrance = mAddingObserverCounter ! =0 || mHandlingEvent;
// Calculate the target state that the newly added observer needs to transition to
State targetState = calculateTargetState(observer);
mAddingObserverCounter++;
// Issue lifecycle events to the observer when its mState is less than the target state and the Observer has not been removed
while ((statefulObserver.mState.compareTo(targetState) < 0
&& mObserverMap.contains(observer))) {
pushParentState(statefulObserver.mState);
// Distribute events
statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
popParentState();
// mState / subling may have been changed recalculate
targetState = calculateTargetState(observer);
}
// False indicates that the Observer is not currently in sync() and is not concurrently added
// Mainly to prevent repeated calls to the sync() method
if(! isReentrance) {// we do sync only on the top level.
// Synchronize all observer states so that they are consistent
sync();
}
mAddingObserverCounter--;
}
// Returns the next state of the current 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
As you can see from the code analysis above, when we add an Observer to the onResume method, the Observer will receive successive callbacks to the ON_CREATE,ON_START, and ON_RESUME events.
Let’s look at the way it distributes events
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
// Obtain the corresponding state according to the event
State next = getStateAfter(event);
moveToState(next);
}
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);
}
private void moveToState(State next) {
// The current state is the same as the transition state
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;
// Synchronize all observer states so that they are consistent
sync();
mHandlingEvent = false;
}
private void sync() {
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
if (lifecycleOwner == null) {
Log.w(LOG_TAG, "LifecycleOwner is garbage collected, you shouldn't try dispatch "
+ "new events from it.");
return;
}
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
The dispatchEvent(lifecycleOwner, owner, ObserverWithState) is called in the backwardPass(lifecycleOwner) and forwardPass(lifecycleOwner) methods. The Event Event) method
void dispatchEvent(LifecycleOwner owner, Event event) {
State newState = getStateAfter(event);
mState = min(mState, newState);
// Notify LifeCycleObsever of the event
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}
Copy the code
At this point the LifecycleRegister process of receiving the event and distributing it to the LifecycleObserver has been analyzed.
Some of the design ideas and patterns that LifeCycle uses
As you can see from the previous section, LifeCycleObserver is just an empty interface. It has sub-interfaces such as LifecycleEventObserver and FullLifecycleObserver, and can even declare lifecycle callbacks as annotations. How is ObserverWithState compatible with different types of LifeCycleObserver?
static class ObserverWithState {
State mState;
LifecycleEventObserver mLifecycleObserver;
ObserverWithState(LifecycleObserver observer, State initialState) {
mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
mState = initialState;
}
/ / to omit...
}
Copy the code
Look at Jetpack (1) -Lifecycle from the source
ObserverWithState passes the LifecycleObserver object to Lifecycling for type-wrapping, syntheses the reflection logic and interface callback logic into a new LifecycleEventObserver object, This unified the Event distribution process into a single entry.
ObserverWithState encapsulates complex reflection logic and interface callback processing and type packaging into LifeCycling classes, decoupling the process of generating a new LifecycleEventObserver object from LifeCycleRegistry to reflect a single responsibility. Enable LifecycleRegistry to complete the distribution of lifecycle events only through the onStateChanged method.
static LifecycleEventObserver lifecycleEventObserver(Object object) {
boolean isLifecycleEventObserver = object instanceof LifecycleEventObserver;
boolean isFullLifecycleObserver = object instanceof FullLifecycleObserver;
// Implement LifecycleEventObserver and FullLifecycleObserver interfaces
if (isLifecycleEventObserver && isFullLifecycleObserver) {
return new FullLifecycleObserverAdapter((FullLifecycleObserver) object,
(LifecycleEventObserver) object);
}
// Only FullLifecycleObserver interface is implemented
if (isFullLifecycleObserver) {
return new FullLifecycleObserverAdapter((FullLifecycleObserver) object, null);
}
// Only LifecycleEventObserver interface is implemented
if (isLifecycleEventObserver) {
return (LifecycleEventObserver) object;
}
/ / to omit...
}
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
FullLifecycleObserverAdapter this class using the adapter pattern, adapter FullLifecycleObserver and LifecycleEventObserver the two interfaces. It implements the LifeCycleEventObserver interface itself, and when onStateChanged, it calls back the corresponding lifecycle methods of the member variables mFullLifecycleObserver and mLifecycleEventObserver, respectively.
Adapter Design Pattern. This pattern is used for adaptation. It converts incompatible interfaces into compatible interfaces so that classes that would otherwise not work together because of incompatible interfaces can work together.
The adapter pattern is used because LifecycleObserver’s subinterfaces are based on interface isolation and are not designed to be comprehensive. The advantage of this is that the implementing class and the caller of the interface can not rely on interface functions that it does not need.
Lifecycle components also use design principles based on interfaces rather than implementation programming. LifeCycle, for example, holds lifecycleObservers that are interfaces, allowing users to customize the LifeCycleObserver for their business. This greatly improves the extensibility and flexibility of Lifecycle components.
There is more to LifeCycling’s source code analysis, but space is limited and this is not at the heart of Lifecycle, so I won’t go into it. Jetpack (1) -Lifecycle will be Lifecycle by Lifecycle
conclusion
Lifecycle makes it easy for Lifecycle components to distribute life-state change events to observers. ActivityLifecycleCallback compared, it is more abstract, decoupling the relationship between the life cycle components and components of the observer, making life cycle components do not need to deal directly with observer component, but will be distributed to Lifecycle status, again by component Lifecycle uniform distributed to the observer, Making the LifecycleOwner component distribution lifecycle easier. In addition, LifecycleRegistry holds LifecycleOwner’s weak reference object in a way that reduces memory leaks and improves code robustness. Implementing programming based on interface programming improves code extensibility and flexibility.
Reference & Thanks
Lifecycle: Lifecycle components & Principles
Jetpack (1) -Lifecycle