Lifecycle profile

Jetpack is a suite of libraries to help developers follow best practices, reduce boilerplate code, and write code that works consistently across Android versions and devices so that developers can focus on the code they care about.

Jetpack was introduced by Google to solve Android’s architectural problems, and it includes a number of components that can help developers build applications more easily.

Lifecycle components are fundamental Lifecycle aware components in the Architectural components of the Jetpack library, providing classes and interfaces that can be used to build Lifecycle aware components. These classes and interfaces can automatically adjust behavior based on the current lifecycle state of an Activity or Fragment, helping developers write leaner, more robust, and easier to maintain code.

Relearn Android: Restore a true Jetpack Lifecycle for you

Lifecycle exists in order to:

1. Achieve consistency of life cycle management, so that “one modification takes effect everywhere”.

2. Enable third-party components to obtain the life cycle status internally at any time, so that they can perform strong life cycle operations such as stopping missed asynchronous services in time.

3. Make it easier and safer for third-party components to trace the life cycle source of the accident during debugging.

Lifecycle before

Before Lifecycle, means managed the Lifecycle by defining Lifecycle components and then calling the corresponding callback component methods in Activity and Fragment Lifecycle methods.

An example of a means management lifecycle

class MyListener { public MyLocationListener(Context context, Void start() {//} void stop() {//} void stop() {//}}Copy the code
class MyActivity extends AppCompatActivity { private MyListener myListener1; private MyListener myListener2; @Override public void onCreate(...) {... } @Override public void onStart() { super.onStart(); myLocationListener1.start(); myLocationListener2.start(); } @override public void onStop() {super.onstop (); myLocationListener1.stop(); myLocationListener2.stop(); // Manage other components that need to respond to the activity lifecycle}... }Copy the code

As shown in the previous example, MyActivity calls custom lifecycle components in each lifecycle method, with each component corresponding to an object. It is likely that MyActivity will need to call multiple custom lifecycle components in each lifecycle method.

Disadvantages of manually managing the life cycle

  1. Difficult to maintain

In a real-world business, where you typically have to manage a lot of pages and a lot of custom lifecycle components, projects are prone to glitches as business iterations and staff adjustments continue.

  1. Components that cannot be customized will start before the Activity/Fragment stops

This is especially true when we need to run an operation for a long time, such as some configuration check in onStart(). This can lead to a race condition in which the onStop() method ends before onStart(), making custom components persist longer than necessary.

Using the Lifecycle

An example of managing the Lifecycle after using Lifecycle

  1. configuration

    A. Add Google’s Maven Repository

    B. build.gradle adds dependencies

Dependencies {val lifecycle_version = "2.0-alpha04" val arch_version = "2.1.0" // ViewModel implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version") // ViewModel utilities for Compose implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version") // LiveData implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version") // Lifecycles only (without ViewModel or LiveData) implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version") // Saved state module for ViewModel implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version") // Annotation processor  kapt("androidx.lifecycle:lifecycle-compiler:$lifecycle_version") // alternately - if using Java8, use the following instead of lifecycle-compiler implementation("androidx.lifecycle:lifecycle-common-java8:$lifecycle_version") // optional - helpers for implementing LifecycleOwner in a Service implementation("androidx.lifecycle:lifecycle-service:$lifecycle_version") // optional - ProcessLifecycleOwner provides a lifecycle for the whole application process implementation("androidx.lifecycle:lifecycle-process:$lifecycle_version") // optional - ReactiveStreams support for LiveData implementation("androidx.lifecycle:lifecycle-reactivestreams-ktx:$lifecycle_version") // optional - Test helpers for LiveData testImplementation("androidx.arch.core:core-testing:$arch_version") }Copy the code
  1. Build pages with a life cycle (observed)

LifecycleOwner interface implementation classes have the Android lifecycle, and the commonly used FragmentActivity and Fragment classes inherit this interface.

  1. Building an observer

Starting with Java8, it is recommended to build LifecycleObserver objects using DefaultLifecycleObserver. Implement only the methods you need

val myObserver = object : DefaultLifecycleObserver { override fun onCreate(owner: LifecycleOwner) { ... } override fun onStop(owner: LifecycleOwner) { ... } } // DefaultLifecycleObserver.java 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
  1. Binds the observed to the observer
// LifecycleOwner's implementation class can get Lifecycle. AddObserver (myObserver)Copy the code

After completing these steps, the bound observer is notified of the page lifecycle change, triggering the method we implemented.

  1. Note: The following examples are not recommended@OnLifecycleEventAnnotation.

Using this annotation requires that apt be used at compile time to generate logic from the annotation and call callback methods based on reflection, which is simply simple to write. Java8 supports interface methods with default implementations, making DefaultLifecycleObserver writing as simple as the @onlifecycleevent annotation, eliminating the performance penalty of reflection.

lifecycle.addObserver(object : LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun onResume() {
    }
})
Copy the code

Source code analysis

Overall flow chart

  1. Changes in the Activity/Fragment life cycle
  2. The ReportFragment/Fragment object distributes lifecycle events to the LifecycleRegistry object
  3. The LifecycleRegistry object handles each of the previously added observers based on lifecycle events

Core types

Lifecycle class

Lifecycle tracks the Lifecycle state of its associated components using two enumerations:

  1. Events, LifecycleOwner Events are triggered when the lifecycle changes, as side of the lifecycle state transition graph
  2. State, the current State of the LifecycleOwner, as points in the lifecycle State transition diagram
public abstract class Lifecycle { ... @MainThread public abstract void addObserver(@NonNull LifecycleObserver observer); @MainThread public abstract void removeObserver(@NonNull LifecycleObserver observer); @MainThread @NonNull public abstract State getCurrentState(); Public enum Event {ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY, ON_ANY; Public static Event downFrom(@nonnull State State) {... } public static Event downTo(@NonNull State state) {... } public static Event upFrom(@NonNull State state) {... } public static Event upTo(@NonNull State state) {... } public State getTargetState() {public getTargetState() {public getTargetState() { }} // Lifecycle status public enum State {// LifecycleOwner destruction status. After this event, the life cycle will not dispatch any more events. For example, for Android.app. Activity, state DESTROYED, // LifecycleOwner's initialization state is reached before the onDestroy call of the Activity. For example, for Android.app. Activity, this is the INITIALIZED state when it was constructed but not yet received onCreate, // the creation state of LifecycleOwner. // For example, for Android.app. Activity, this state is reached in two cases: after onCreate calls; CREATED just before the onStop call, // Startup state of LifecycleOwner. // For example, for Android.app. Activity, this state is reached in two cases: after onStart; STARTED before the onPause call, // LifecycleOwner resumes its state. // For example, for Android.app. Activity, this state is reached after calling onResume. RESUMED; public boolean isAtLeast(@NonNull State state) { return compareTo(state) >= 0; }}}Copy the code

Life cycle state transition diagram

When the Event is triggered:

  • ON_CREATE, ON_START, and ON_RESUME events are distributed after the LifecycleOwner method is executed;
  • The ON_PAUSE, ON_STOP, and ON_DESTROY events are distributed before the LifecycleOwner method is called;

LifecycleOwner interface

Objects that mark their implementation classes have an Android life cycle

public interface LifecycleOwner {
    @NonNull
    Lifecycle getLifecycle();
}
Copy the code

LifecycleObserver interface

The tagging implementation class can observe the lifecycle

public interface LifecycleObserver { } public interface LifecycleEventObserver extends LifecycleObserver { void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event); } 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); } 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

Implementation approach

LifecycleOwner: Hands the lifecycle event to the corresponding LifecycleRegistry

Whether AppCompatActivity, Fragment, or any other object that implements the LifecycleOwner interface, the implementation logic is the same, handing life cycle events to their respective LifecycleRegistry to handle.

AppCompatActivity implements the LifecycleOwner interface

AppCompatActivity implements LifecycleOwner interface and is done in ComponentActivity.

public class ComponentActivity extends androidx.core.app.ComponentActivity implements LifecycleOwner { ... Private Final LifecycleRegistry = new LifecycleRegistry(this); public Lifecycle getLifecycle() { return mLifecycleRegistry; } public ComponentActivity() { Lifecycle lifecycle = getLifecycle(); . 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 ) { ... }}}); } getLifecycle().addObserver(new LifecycleEventObserver () { @Override public void onStateChanged ( @NonNull LifecycleOwner source, @NonNull Lifecycle.Event event ) { if ( event == Lifecycle.Event.ON_DESTROY ) { ... }}}); getLifecycle().addObserver(new LifecycleEventObserver () { @Override public void onStateChanged ( @NonNull LifecycleOwner source, @NonNull Lifecycle.Event event ) { ensureViewModelStore () ; getLifecycle () .removeObserver ( this ) ; }}); if (19 <= SDK_INT && SDK_INT <= 23) { getLifecycle () .addObserver ( new ImmLeaksCleaner ( this )) ; }}... protected void onCreate(@Nullable Bundle savedInstanceState) { ... super.onCreate(savedInstanceState); . / / registered ReportFragment ReportFragment injectIfNeededIn (this); . } @NonNull @Override public Lifecycle getLifecycle() { return mLifecycleRegistry; }}Copy the code

ComponentActivity registers ReportFragment, delegating responsibility for handling life cycle events to it.

Two ReportFragment distribution methods

Upon receiving a life cycle event for ComponentActivity, The ReportFragment dispatches it to the registered callback class.

ReportFragmentjava public static void injectIfNeededIn(Activity activity) { if (Build.VERSION.SDK_INT >= 29) { LifecycleCallbacks.registerIn(activity); Add ReportFragment} / / / / and ProcessLifecycleOwner and inherit the support FragmentActivity Activity is compatible with android. The app. FragmentManager manager = activity.getFragmentManager(); if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) { manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit(); manager.executePendingTransactions(); }}Copy the code

The ReportFragment. ‘ ‘injectIfNeededI’ ‘(Activity Activity) can be distributed in either of the following ways:

  1. Register the Activity when the system version number of the running device is >= 29LifecycleCallbacksObject.LifecycleCallbacksisApplication.ActivityLifecycleCallbacksThe subclass. After registration, the Activity’s life cycle changesLifecycleCallbacksTo call the corresponding methodReportFragment.dispatchMethods.

The ReportFragment.Dispatch method is where the activity actually dispatches life cycle events, described below.

@RequiresApi(29) static class LifecycleCallbacks implements Application.ActivityLifecycleCallbacks { static void RegisterIn the Activity (Activity) {/ / let the Activity registered LifecycleCallbacks Activity. RegisterActivityLifecycleCallbacks (new LifecycleCallbacks () ); } @Override public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle bundle) { } @Override public void onActivityPostCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) { dispatch(activity, Lifecycle.Event.ON_CREATE); } @Override public void onActivityStarted(@NonNull Activity activity) { } @Override public void onActivityPostStarted(@NonNull Activity activity) { dispatch(activity, Lifecycle.Event.ON_START); } @Override public void onActivityResumed(@NonNull Activity activity) { } @Override public void onActivityPostResumed(@NonNull Activity activity) { dispatch(activity, Lifecycle.Event.ON_RESUME); } @Override public void onActivityPrePaused(@NonNull Activity activity) { dispatch(activity, Lifecycle.Event.ON_PAUSE); } @Override public void onActivityPaused(@NonNull Activity activity) { } @Override public void onActivityPreStopped(@NonNull Activity activity) { dispatch(activity, Lifecycle.Event.ON_STOP); } @Override public void onActivityStopped(@NonNull Activity activity) { } @Override public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle bundle) { } @Override public void onActivityPreDestroyed(@NonNull Activity activity) { dispatch(activity, Lifecycle.Event.ON_DESTROY); } @Override public void onActivityDestroyed(@NonNull Activity activity) { } }Copy the code
  1. Add a ReportFragment without a UI to the Activity

Each lifecycle event of the Activity is indirectly sensed through The ReportFragment, and the Dispatch method is called if the version number is greater than 29.

ReportFragment.java private void dispatchCreate(ActivityInitializationListener listener) { if (listener ! = null) { listener.onCreate () ; }}... @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); dispatchCreate(mProcessListener); dispatch(Lifecycle.Event.ON_CREATE); } @Override public void onStart() { super.onStart(); dispatchStart(mProcessListener); dispatch(Lifecycle.Event.ON_START); }... @Override public void onDestroy() { super.onDestroy(); dispatch(Lifecycle.Event.ON_DESTROY); // just want to be sure that we won't leak reference to an activity mProcessListener = null; } private void dispatch(@NonNull Lifecycle.Event event) { if (Build.VERSION.SDK_INT < 29) { dispatch( getActivity () , event ) ; } } interface ActivityInitializationListener { void onCreate(); void onStart(); void onResume(); }Copy the code
Dispatch method: Dispatches events

The Dispatch method hands the lifecycle events to the activity’s LifecycleRegistry object for processing.

static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) { if (activity instanceof LifecycleOwner) { Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle(); If (lifecycle instanceof LifecycleRegistry) {// LifecycleRegistry belongs to the Activity ((LifecycleRegistry)) lifecycle).handleLifecycleEvent(event); }}}Copy the code

Fragment implements the LifecycleOwner interface

Fragments do not need to distribute lifecycle events and hand lifecycle events directly to LifecycleRegistry objects when lifecycle changes.

Fragment.java LifecycleRegistry mLifecycleRegistry; public Fragment() { initLifecycle(); } private void initLifecycle() { mLifecycleRegistry = new LifecycleRegistry(this); . } public Lifecycle getLifecycle() { return mLifecycleRegistry; } void performCreate(Bundle savedInstanceState) { ... onCreate(savedInstanceState); mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE); } void performStart() { onStart(); mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START); . }...Copy the code

LifecycleRegistry: Concrete processing logic

LifecycleRegistry masks the specific type of LifecycleOwner so that other classes only need to forward lifecycle events, but its methods can only be executed on the main thread. LifecycleRegistry implements specific event callbacks and state management to be more unified and normalized.

There are two situations in which lifecycle events need to be handled:

  1. Gets the lifecycle events distributed by the Dispatch method
  2. Adding an Observer progressively triggers callbacks prior to the corresponding lifecycle

LifecycleRegistry internal logic

Add observer

The addObserver method can only be used on the main thread

Java // Hold virtual reference private Final WeakReference<LifecycleOwner> mLifecycleOwner; Public void addObserver (@ NonNull LifecycleObserver observer) {/ / check the main thread enforceMainThreadIfNeeded (" addObserver "); State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED; // Wrap the Observer and lifecycle states as ObserverWithState objects, ObserverWithState statefulObserver = New ObserverWithState(Observer, initialState); ObserverWithState Previous = mobServerMap. putIfAbsent(Observer, statefulObserver); ObserverWithState previous = mobServerMap. putIfAbsent(Observer, statefulObserver); if (previous ! = null) { return; } // check the virtual reference lifecycleOwner lifecycleOwner lifecycleOwner = mlifecycleowner.get (); if (lifecycleOwner == null) { return; } // Not in the process of adding an observer and not in the process of handling life cycle events Boolean isReentrance = mAddingObserverCounter! = 0 || mHandlingEvent; // Desired observer lifecycle State targetState = calculateTargetState(observer); mAddingObserverCounter++; / / comment 3 while ((statefulObserver.mState.com pareTo (targetState) < 0 && mObserverMap. The contains (observer))) {/ / to the observer PushParentState (stateFulobServer.mstate); Event.upfrom (stateFulobServer.mState); event.upfrom (stateFulobServer.mState); . / / processing life cycle state statefulObserver dispatchEvent (lifecycleOwner, event); // Remove mState popParentState (); TargetState = calculateTargetState (observer); } if (! isReentrance) { // we do sync only on the top level. sync () ; } mAddingObserverCounter--; }Copy the code
static class ObserverWithState { State mState; LifecycleEventObserver mLifecycleObserver; ObserverWithState(LifecycleObserver observer, The State initialState) {/ / comment 2 mLifecycleObserver = Lifecycling. LifecycleEventObserver (observer); mState = initialState; } void dispatchEvent(LifecycleOwner owner, Event event) { State newState = event.getTargetState(); mState = min(mState, newState); / / trigger our custom callback mLifecycleObserver onStateChanged (the owner, the event); mState = newState; }}Copy the code
  1. willLifecycleObserverThe object Observer is wrapped asObserverWithStateObject, giving the Observer a lifecycle state.
  2. Will the observer to <LifecycleObserver.ObserverWithState> is stored in themObserverMapIn the. whileObserverWithStateWill the incomingLifecycleObserverObject wrapped asLifecycleEventObserver.

Adapter mode

Lifecycling uniformly converts the LifecycleEventObserver and LifecycleEventObserver types to subtypes of LifecycleEventObserver so that callbacks are uniformly triggered. Before it is recommended to use FullLifecycleObserver is converted to FullLifecycleObserverAdapter, OnLifecycleEvent method are recommended not to use it according to the specific logical comments generated by reflection calls again.

Lifecycling.java static LifecycleEventObserver lifecycleEventObserver(Object object) { boolean isLifecycleEventObserver = object instanceof LifecycleEventObserver; boolean isFullLifecycleObserver = object instanceof FullLifecycleObserver; FullLifecycleObserver if (isLifecycleEventObserver && isFullLifecycleObserver) {return new FullLifecycleObserverAdapter (( FullLifecycleObserver ) object, ( LifecycleEventObserver ) object ) ; } if (isFullLifecycleObserver) { return new FullLifecycleObserverAdapter (( FullLifecycleObserver ) object, null ) ; } if (isLifecycleEventObserver) { return ( LifecycleEventObserver ) object; } // @onlifecycleEvent final Class<? > 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
public interface LifecycleEventObserver extends LifecycleObserver {
     void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event);
}
Copy the code
  1. Synchronizing the latest lifecycle events to the added Observer triggers our custom callback. For example, if you add an Observer when your activity is in the RESUMED state, the observer receives itCREATED,STARTED,RESUMEDThree of the Event.
Delete observer

The removeObserver method removes the observer from the mObserverMap

 public void removeObserver(@NonNull LifecycleObserver observer) {
       mObserverMap.remove(observer);
 }
Copy the code
Update the status, triggering the Observer

LifecycleRegistry calls moveToState to update the status after receiving the ReportFragment event. The moveToState method is responsible for determining whether to update, and the actual handling of all observers is in the sync() method.

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) { ... moveToState(event.getTargetState()); } 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

The sync() method updates the life cycle of all ObserverWithState objects in the mObserverMap through the backwardPass and forwardPass methods.

private void sync() { ... while (! isSynced()) { mNewEventOccurred = false; if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) { backwardPass(lifecycleOwner); } Map.Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest(); if (! mNewEventOccurred && newest ! = null && mState.compareTo(newest.getValue().mState) > 0) { forwardPass(lifecycleOwner); } } mNewEventOccurred = false; } private void forwardPass(LifecycleOwner lifecycleOwner) { ... while (ascendingIterator.hasNext() && ! mNewEventOccurred) { while ((observer.mState.compareTo(mState) < 0 && ! mNewEventOccurred && mObserverMap.contains(entry.getKey()))) { ... // Trigger the observer callback observer.dispatchEvent(lifecycleOwner, event); } } } private void backwardPass(LifecycleOwner lifecycleOwner) { while (descendingIterator.hasNext() && ! mNewEventOccurred) { ... while ((observer.mState.compareTo(mState) > 0 && ! mNewEventOccurred && mObserverMap.contains(entry.getKey()))) { ... // Trigger the observer callback observer.dispatchEvent(lifecycleOwner, event); }}}Copy the code

Reference documentation

Lifecycle website

This article will take you into understanding Lifecycle.

Jetpack AAC

Jetpack (1) -Lifecycle