Summary of Lifecycle

Google has released Android Architecture Components to us, and it talks about how Android Components handle Lifecycles. At the same time, how to use the android.arch. Lifecycle class provided by the android.arch. Lifecycle package to control data, listeners and other lifecycle? At the same time, lifecycle of LiveData and ViewModel also depends on the lifecycle framework. More recently, The Android Architecture Components have been released and Lifecycle has been built into supportActivities (the base class for AppCompatActivity) and fragments.

Introduction to the

Lifecycle is a class that stores information about the Lifecycle state of a component (such as acitivity or fragment) and allows other objects to observe this state. Thus, the external implementation of listening, can enable us to timely according to the component lifecycle changes to take corresponding actions, such as releasing resources, so as to avoid memory leaks and program crashes.

When developing an application, we might implement a function based on a series of life cycles. A common previous pattern is to implement dependent components behavior in the lifecycle methods of acitivity and fragment, however this pattern leads to messy code and a proliferation of errors. See the demo below.

class MyPresenter{
    public MyPresenter(a) {}void create(a) {
        //do something
    }

    void start(a) {
        //do something
    }
    
    void destroy(a) {
        //do something}}class MyActivity extends AppCompatActivity {
    private MyPresenter presenter;

    @Override
    public void onCreate(...). {
        presenter= new MyPresenter ();
        presenter.create();
    }
    
	@Override
    public void onStart(a) {
        super.onStart();
        presenter.start();
    }
    
    @Override
    public void onDestroy(a) {
        super.onDestroy(); presenter.destory(); }}Copy the code

Although this example seems fine, in a real application you would end up with too many calls to update the UI and other components corresponding to the current lifecycle state. To manage multiple components, you have to add a lot of code to the lifecycle methods such as onStart() and onStop(), which can be difficult to maintain.

Worse, there is no guarantee that these components will start before the activity or fragment is stopped, especially if you need to perform a lengthy operation, such as some configuration check in onStart(). This creates a race condition that causes the onStop() method to end before onStart(), thus making these components live too long.

class MyActivity extends AppCompatActivity {
    private MyPresenter presenter;

    @Override
    public void onCreate(...). {
        presenter= new MyPresenter ();
        presenter.create();
    }
    
	@Override
    public void onStart(a) {
        super.onStart();
        Util.checkUserStatus(result -> {
            // what if this callback is invoked AFTER activity is stopped?
            if(result) { presenter.start(); }}); }@Override
    public void onDestroy(a) {
        super.onDestroy(); presenter.destory(); }}Copy the code

In order to reuse and not to make the application components become too bloated, the implementation of this function will choose to decouple the lifecycle components into a single component. This can be easily used in an application component, such as an Activity, Fragment, or Service.

Officially, Android calls it a lifecycle-aware component, which responds to state changes in the lifecycle of other components, such as activities and fragments, to help you write more organized, lightweight, and maintainable code.

By using life-cycle aware components, you can move the code for related components out of the lifecycle methods and into the components themselves.

To make it easier for developers to create lifecycle aware components, the Android.arch.Lifecycle package provides classes and interfaces that let you build lifecycle aware components.

Note: To import Android.arch. Lifecycle into your Android project, see Adding Android Architectural Components to your Project.

Most application components defined in the Android framework have lifecycles that are managed by the operating system, or by the framework code running in your processes. They are essential to the proper functioning of Android, so your application must respect them or risk memory leaks or even app crashes.

Demo

  • Prestener inherits the LifecycleObserver interface

    public interface IPresenter implements LifecycleObserver {
    
        @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
        void onCreate(@NotNull LifecycleOwner owner);
    
        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
        void onDestroy(@NotNull LifecycleOwner owner);
    
        @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
        void onLifecycleChanged(@NotNull LifecycleOwner owner,
                                @NotNull Lifecycle.Event event);
    }
    
    public class BasePresenter implements IPresenter {
    
        private static final String TAG = "BasePresenter";    
    
        @Override
        public void onLifecycleChanged(@NotNull LifecycleOwner owner, 
                                       @NotNull Lifecycle.Event event) {}@Override
        public void onCreate(@NotNull LifecycleOwner owner) {
            Log.d(TAG, "BasePresenter.onCreate" + this.getClass().toString());
        }
    
        @Override
        public void onDestroy(@NotNull LifecycleOwner owner) {
            Log.d(TAG, "BasePresenter.onDestroy" + this.getClass().toString()); }}public class MainPresenter extends BasePresenter {
        / /...
    }
    
    Copy the code

    Here I directly list the events that I want to observe in the lifecycle of the Presenter and encapsulate them into the BasePresenter, so that each subclass of the BasePresenter can be aware of the lifecycle events of the Activity container and override the corresponding behavior in the methods of the subclass.

  • Add an Observer to the Activity/Fragment

    public class MainActivity extends AppCompatActivity {
        private IPresenter mObserver;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d("tag"."onCreate" + this.getClass().toString());
            setContentView(R.layout.activity_main);
            mObserver = new MainPresenter(this);
            getLifecycle().addObserver(mObserver);/ / add LifecycleObserver
        }
    
        @Override
        protected void onDestroy(a) {
            Log.d("tag"."onDestroy" + this.getClass().toString());
            super.onDestroy(); }}Copy the code

    In this way, whenever the Activity has a corresponding lifecycle change, the Presenter will execute the corresponding event annotation method, and as long as the annotation is declared, the LifecycleObserver can observe the corresponding lifecycle event.

Source code analysis

To summarize briefly, using a diagram from Android Architecture component I — Lifecycle:

Let’s first pick out the important classes:

  • LifecycleObserver interface: The class that implements the interface can be annotated by theLifecycleOwnerOf the classaddObserver(LifecycleObserver o)Method registration, after being registered,LifecycleObserverYou can see thatLifecycleOwnertheLife cycle event.
  • LifecycleOwner interface: The class that implements this interface holds a Lifecycle object, and changes to the interface’s Lifecycle object are observed by its registered observer LifecycleObserver and trigger its corresponding event.
  • Lifecycle: Unlike the LifecycleOwner, which itself holds a Lifecycle object, LifecycleOwner retrieves the internal Lifecycle object through its getLifecycle().
  • State(State of the current lifecycle) : as shown in the figure.
  • Event(Event corresponding to current Lifecycle change) : As shown in the figure, when Lifecycle changes occur, such as onCreate, an ON_CREATE Event will be automatically emitted.

In simple terms, LifecycleOwner is used to provide Lifecycle, LifecycleObserver to listen for state changes at Lifecycle, and Lifecycle is an abstraction of the Lifecycle state of an Activity or Fragment.

Now that we know what these classes and interfaces are, it’s easy to analyze the principles. Let’s look at the actual Fragment/Activity class and the connection between the above classes or interfaces:

LifecycleOwner

public interface LifecycleOwner {    
    /**     
    * Returns the Lifecycle of the provider.     
    *     
    * @return The lifecycle of the provider.     
    */    
    @NonNull    
    Lifecycle getLifecycle(a);
}
Copy the code

LifecycleOwner is an interface that contains only one method (getLifecycle()) and uses @nonnull to force us to return a Lifecycle object.

LifecycleOwner is used to indicate that a class has Lifecycle. The only getLifecycle() method must be implemented by that class. On the other hand, if you are trying to manage the lifecycle of the entire application process, see ProcessLifecycleOwner.

This interface abstracts ownership of Lifecycle from its respective classes, such as Fragments and AppCompatActivity, and allows users to write components that collaborate with it. Any custom application class can implement this interface.

Components that implement the LifecycleObserver interface can work seamlessly with components that implement the LifecycleOwner, because the latter can provide a lifecycle that the former can register to observe.

If a library provides classes that need to be coordinated with the Android lifecycle, we recommend that you use lifecycle aware components. Users of your library can easily integrate these components without having to manually manage the lifecycle.

The LifecycleOwner interface has been implemented for Fragments and activities in the support library in versions 26.1.0 and later.

androidx.fragment.app.Fragment

Let’s take a look at the implementation of fragments in androidx

public class Fragment implements. .LifecycleOwner {
     
    LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
    
    @Override
    public Lifecycle getLifecycle(a) {
        return mLifecycleRegistry;
    }
    
    void performCreate(Bundle savedInstanceState) {
        //1. Execute the lifecycle method first
        onCreate(savedInstanceState);
        / /... Omit code
        //2. Life cycle event distribution
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
    }
    
    void performStart(a) {
        onStart();
        / /...
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
    }
    
    void performResume(a) {
        onResume();
        / /...
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
    }
    
    void performPause(a) {
        //3. Note that the order of calls has changed
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
        / /...
        onPause();
    }
    
     void performStop(a) {
       mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
        / /...
        onStop();
    }

    void performDestroy(a) {
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
        / /...onDestroy(); }}Copy the code

Different fragments go through different lifecycles, except for the lifecycle method onCreate/onStart/…. that is exposed to us /onDestroy, etc. The Lifecycle object inside the Fragment (that is, mLifecycleRegistry) also passes the Lifecycle event as an argument to the LifecycleRegistry#handleLifecycleEvent() method. This method is analyzed in the following article.

Also, you’ll notice that the Fragment performCreate(), performStart(), and performResume() call their own onXXX() method first, Then call the handleLifecycleEvent() method of LifecycleRegistry; In performPause(), performStop(), and performDestroy(), LifecycleRegistry’s handleLifecycleEvent() method is called first and then onXXX() itself.

Refer to the sequence diagram in Android Architecture Component I — Lifecycle:

androidx.core.app.ComponentActivity

Let’s look at the implementation of ComponentActivity in androidx

public class ComponentActivity extends Activity implements LifecycleOwner.ViewModelStoreOwner.SavedStateRegistryOwner.OnBackPressedDispatcherOwner{
    private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        / /...
        ReportFragment.injectIfNeededIn(this);
        / /...
    }
    
    @Override
    public Lifecycle getLifecycle(a) {
        returnmLifecycleRegistry; }}Copy the code

Is the core of lifecycle related code above, you can see it is not like fragments in each life cycle function call mLifecycleRegistry. HandleLifecycleEvent to emit events, So how does it make the LifecycleObserver feel the lifecycle changes in ComponentActivity?

Actually the key lies in the onCreate () method of ReportFragment. InjectIfNeededIn (this).

Let’s look at the ReportFragment

public class ReportFragment extends Fragment {
    private static final String REPORT_FRAGMENT_TAG = "androidx.lifecycle"
            + ".LifecycleDispatcher.report_fragment_tag";

    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(); }}static ReportFragment get(Activity activity) {
        return (ReportFragment) activity.getFragmentManager().findFragmentByTag(
                REPORT_FRAGMENT_TAG);
    }

    private ActivityInitializationListener mProcessListener;

    private void dispatchCreate(ActivityInitializationListener listener) {
        if(listener ! =null) { listener.onCreate(); }}private void dispatchStart(ActivityInitializationListener listener) {
        if(listener ! =null) { listener.onStart(); }}private void dispatchResume(ActivityInitializationListener listener) {
        if(listener ! =null) { listener.onResume(); }}@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;
    }

    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); }}}void setProcessListener(ActivityInitializationListener processListener) {
        mProcessListener = processListener;
    }

    interface ActivityInitializationListener {
        void onCreate(a);

        void onStart(a);

        void onResume(a); }}Copy the code

The ReportFragment code is simple. It overwrites the Lifecycle function and calls the Dispatch (lifecycle.Event Event) method to distribute the Lifecycle events. This is where “Lifecycle awareness” comes in. It’s a common practice to register a UI-less Fragment, also called a Headless Fragment, with an Activity to separate out various Activity callbacks, such as the RxPermission permission library, And Airbnb’s open source DeepLinkDispatch for URL redirects (the former uses an empty Fragment, the latter an empty Activity)

The LifecycleObserver has a clear diagram of how Activity lifecycle changes are transmitted to the LifecycleObserver:

(LifecycleRegistry) lifecycle).handlelifecyCleEvent (Event) method will be called eventually.

android.app.Activity

This is a normal Activity. If you want this Activity to be customized as a LifecycleOwner, you can use the LifecycleRegistry class

Many articles on the Internet are done in the following way

public class MyActivity extends Activity implements LifecycleOwner {
    private LifecycleRegistry lifecycleRegistry;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        lifecycleRegistry = new LifecycleRegistry(this);
        lifecycleRegistry.markState(Lifecycle.State.CREATED);
    }

    @Override
    public void onStart(a) {
        super.onStart();
        lifecycleRegistry.markState(Lifecycle.State.STARTED);
    }

    @NonNull
    @Override
    public Lifecycle getLifecycle(a) {
        returnlifecycleRegistry; }}Copy the code

Train of thought is to instantiate a LifecycleRegistry, then rewrite the Activity life cycle function, again through LifecycleRegistry. MarkState to distribute events.

Although by rewriting the Activity life cycle, and through the lines in each method only add a lifecycleRegistry. MarkState () code can realize the life cycle of perception. But programmers, who are lazy people who promote social development, naturally want to free their right hand in a simpler way. There are more ways than difficulties.

As we know, the core of inheriting AppCompactActivity is to inject an empty ReportFragment into the Activity. Can we also dynamically inject the ReportFragment into the Activity in this way?

The answer is yes, and Google has done it for us.

Google provides us with a Extensions library that we need to import separately:

implementation 'androidx. Lifecycle: lifecycle - extensions: 2.0.0'
Copy the code

After introducing this library, we will use it in much the same way as we inherited AppCompactActivity. The only difference is that we will need to implement our own LifecycleOwner and provide a LifecycleRegistry (don’t worry, one line of code, just use the ready-made one).

public class MyActivity extends Activity implements LifecycleOwner {
    private LifecycleRegistry lifecycleRegistry;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        lifecycleRegistry = new LifecycleRegistry(this);
        // It is no longer necessary to call the markstate method manually
        //lifecycleRegistry.markState(Lifecycle.State.CREATED);
    }

    @Override
    public void onStart(a) {
        super.onStart();
        // It is no longer necessary to call the markstate method manually
       	// lifecycleRegistry.markState(Lifecycle.State.STARTED);
    }

    @NonNull
    @Override
    public Lifecycle getLifecycle(a) {
        returnlifecycleRegistry; }}Copy the code

Isn’t it amazing how this works? Let’s push it down the code:

Command/Ctrl+ click on the ReportFragment and find the ReportFragment using two classes: LifecycleDispatcher. Java and ProcessLifecycleOwner. Java these two classes, and the two are extensions of this class library.

Then we will track ReportFragment first. InjectIfNeededIn (activity) in LifecycleDispatcher. Call in Java classes:

class LifecycleDispatcher {

    static class DispatcherActivityCallback extends EmptyActivityLifecycleCallbacks {

        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            ReportFragment.injectIfNeededIn(activity);
        }

        @Override
        public void onActivityStopped(Activity activity) {}@Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}}private LifecycleDispatcher(a) {}}Copy the code

ReportFragment. InjectIfNeededIn (activity) in this line of code is LifecycleDispatcher DispatcherActivityCallback static inner class OnActivityCreated (…). Method. And DispatcherActivityCallback inherited from EmptyActivityLifecycleCallbacks EmptyActivityLifecycleCallbacks is what? It is actually the Application. The empty ActivityLifecycleCallbacks interface implementation class.

class EmptyActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}@Override
    public void onActivityStarted(Activity activity) {}@Override
    public void onActivityResumed(Activity activity) {}@Override
    public void onActivityPaused(Activity activity) {}@Override
    public void onActivityStopped(Activity activity) {}@Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}@Override
    public void onActivityDestroyed(Activity activity) {}}Copy the code

Go back to the source code for LifecycleDispatcher above, Find DispatcherActivityCallback static inner class is instantiated in LifecycleDispatcher class static method init (), in this method the listener registration:

class LifecycleDispatcher {

    private static AtomicBoolean sInitialized = new AtomicBoolean(false);

    static void init(Context context) {
        if (sInitialized.getAndSet(true)) {
            return;
        }
        ((Application) context.getApplicationContext())
                .registerActivityLifecycleCallbacks(new DispatcherActivityCallback());
    }

   / /...
}
Copy the code

There, he saw through the Application of real registerActivityLifecycleCallbacks to register the listener.

Continue tracking LifecycleDispatcher#init(…) Method is invoked, it entered the ProcessLifecycleOwnerInitializer class onCreate () method:

public class ProcessLifecycleOwnerInitializer extends ContentProvider {
    @Override
    public boolean onCreate(a) {
        LifecycleDispatcher.init(getContext());
        ProcessLifecycleOwner.init(getContext());
        return true;
    }
	/ /...
}
Copy the code

ProcessLifecycleOwnerInitializer is inherited from the ContentProvider, in its onCreate () method, has carried on the LifecycleDispatcher initialization, ProcessLifecycleOwner is also initialized. The ProcessLifecycleOwner is described later.

By looking at the source code, you can see that it has an empty implementation of the various methods of the ContentProvider. In fact, this is an implicit load that takes advantage of the ContentProvider. Its onCreate() method is executed before the Application#onCreate() method. In this way, it can listen to the Activity creation through the Application and determine whether an empty UI ReportFragment has been added. If not, add it. This design is really wonderful.

Contentproviders are used to an Application in the same way that Headless Fragments are used to an Activity, in order to avoid inheritance of system components. Android-contentprovider Destruction /lifecycle Stack Overflow android-ContentProvider Destruction /lifecycle Stack Overflow

As we know, all four components are to be lived in the AndroidManifest.xml file. That the ContentProvider type ProcessLifecycleOwnerInitializer is in when to declare?

We find the Extensions library and see where it was downloaded as follows:

In Android Studio, switch to Project mode and locate the class in External Libraries. Right-click the classes.jar pointed to by the arrow in the following image and select display it locally.

In the parent directory of this JAR is androidManifest.xml


      
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="androidx.lifecycle.process" >
    <uses-sdk android:minSdkVersion="14" />
    <application>
        <provider
            android:name="androidx.lifecycle.ProcessLifecycleOwnerInitializer"
            android:authorities="${applicationId}.lifecycle-process"
            android:exported="false"
            android:multiprocess="true" />
    </application>
</manifest>
Copy the code

And here we found the statement.

The AndroidManifest.xml here is eventually merged into the AndroidManifest.xml file of our app Module.

At the end of the backward push, let’s go back and comb it again:

  1. ProcessLifecycleOwnerInitializer registered in the manifest file, the provider in onCreate. Call the LifecycleDispatcher init (getContext ())

  2. The lifecyCleDispatcher.init (getContext()) method calls ((Application) context.getApplicationContext()).registerActivityLifecycleCallbacks(new DispatcherActivityCallback());

  3. The onActivityCreated DispatcherActivityCallback calls the ReportFragment. InjectIfNeededIn;

  4. ReportFragment. InjectIfNeededIn method the ReportFragment all life cycle of the call to join in our activity

  5. Its dispatch() method is called at each lifecycle of the ReportFragment.

  6. Dispatch () calls the LifecycleRegister’s handleLifecycleEvent().

All three cases are analyzed, and at the end of the day, everyone is calling the handleLifecycleEvent() of LifecycleRegister

So let’s examine the LifecycleRegistry class next

LifecycleRegistry inherits from the Lifecycle class

We can look at Lifecycle first

Life cycle (Lifecycle )

public abstract class Lifecycle {
    /** * Adds a LifecycleObserver that will be notified when the LifecycleOwner changes * state. * <p> * The given observer  will be brought to the current state of the LifecycleOwner. * For example, if the LifecycleOwner is in {@link State#STARTED} state, the given observer
     * will receive {@link Event#ON_CREATE}, {@link Event#ON_START} events.
     *
     * @param observer The observer to notify.
     */
    @MainThread
    public abstract void addObserver(@NonNull LifecycleObserver observer);

    /** * Removes the given observer from the observers list. * <p> * If this method is called while a state change is being  dispatched, * <ul> * <li>If the given observer has not yet received that event, it will not receive it. * <li>If the given observer has more than 1 method that observes the currently dispatched * event and at least one of them received the event, all of them will receive the event and * the removal will happen afterwards. * </ul> * *@param observer The observer to be removed.
     */
    @MainThread
    public abstract void removeObserver(@NonNull LifecycleObserver observer);

    /**
     * Returns the current state of the Lifecycle.
     *
     * @return The current state of the Lifecycle.
     */
    @MainThread
    @NonNull
    public abstract State getCurrentState(a);

    // Events correspond to each lifecycle of an activity
	// The ON_ANY event can represent any of the above.
	// For example, an ON_CREATE event is generated when an Activity's onCreate() lifecycle method is called. Observers can listen to this event to process the Activity's current lifecycle.
    @SuppressWarnings("WeakerAccess")
    public enum Event {
       ON_CREATE,    // The onCreate event used to match the lifecycle owner.
       ON_START,     // The onStart event used to match the lifecycle owner.
       ON_RESUME,    // The onResume event used to match the lifecycle owner.
       ON_PAUSE,     // The onCreate event used to match the lifecycle owner.
       ON_STOP,      // The onStop event to match the lifecycle owner.
       ON_DESTROY,   // The onDestroy event used to match the lifecycle owner.
       ON_ANY        // All events that match the lifecycle owner.

    }

    /**
     * Lifecycle states. You can consider the states as the nodes in a graph and
     * {@link Event}s as the edges between these nodes.
     */
    @SuppressWarnings("WeakerAccess")
    public enum State {
        /**
         * Destroyed state for a LifecycleOwner. After this event, this Lifecycle will not dispatch
         * any more events. For instance, for an {@link android.app.Activity}, this state is reached
         * <b>right before</b> Activity's {@link android.app.Activity#onDestroy() onDestroy} call.
         */
        DESTROYED,

        /**
         * Initialized state for a LifecycleOwner. For an {@link android.app.Activity}, this is
         * the state when it is constructed but has not received
         * {@link android.app.Activity#onCreate(android.os.Bundle) onCreate} yet.
         */
        INITIALIZED,

        /**
         * Created state for a LifecycleOwner. For an {@link android.app.Activity}, this state
         * is reached in two cases:
         * <ul>
         *     <li>after {@link android.app.Activity#onCreate(android.os.Bundle) onCreate} call;
         *     <li><b>right before</b> {@link android.app.Activity#onStop() onStop} call.
         * </ul>
         */
        CREATED,

        /**
         * Started state for a LifecycleOwner. For an {@link android.app.Activity}, this state
         * is reached in two cases:
         * <ul>
         *     <li>after {@link android.app.Activity#onStart() onStart} call;
         *     <li><b>right before</b> {@link android.app.Activity#onPause() onPause} call.
         * </ul>
         */
        STARTED,

        /**
         * Resumed state for a LifecycleOwner. For an {@link android.app.Activity}, this state
         * is reached after {@link android.app.Activity#onResume() onResume} is called.
         */
        RESUMED;

        /**
         * Compares if this State is greater or equal to the given {@code state}.
         *
         * @param state State to compare with
         * @return true if this State is greater or equal to the given {@code state}
         */
        public boolean isAtLeast(@NonNull State state) {
            return compareTo(state) >= 0; }}}Copy the code

The Lifecycle class represents the Lifecycle of an Android application component, which is the observed. This is an abstract class whose implementation is the LifecycleRegistry class.

Lifecycle objects have three methods:

  • Add an observer:void addObserver(LifecycleObserver observer).
  • Delete observer:void removeObserver(LifecycleObserver observer). –
  • Get the current status:State getCurrentState().

Lifecycle’s two key methods are LifecycleObserver parameters

So before analyzing LifecycleRegistry let’s take a look at LifecycleObserver

LifecycleObserver

LifecycleObserver overview

The tagged interface LifecycleObserver represents a lifecycle observer and is a lifecycle aware component.

public interface LifecycleObserver {}Copy the code

This interface is used to declare that its implementation class is a lifecycle observer, where we will receive LifecycleOwner lifecychange events and then do our own logic.

But when we looked at the LifecycleObserver interface, our first impression was strange: the interface was empty. So how do we accept life-cycle changing events? (Usually the normal callback interface)

In fact, Google’s approach is to use the annotation OnLifecycleEvent, LifecycleObserver only serves as a declaration and constraint. The number of its internal inheritance is as follows:

Seeing so many similar interfaces, I guess this is because there are so many lifecycle hooks, and if they were all in the interface, the implementer would have to add so many empty implementation methods that the readability would be reduced.

Such as FullLifecycleObserver

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

This interface declares all the lifecycle functions. If we implement this interface, we have to override all the interfaces, but we don’t have to use so many. This interface is not public, so we can’t implement it.

We know that using annotations is mostly reflection parsing, which is a performance issue, and of course using APT solves this problem at compile time. More on this later.

If we don’t want to use annotations and we don’t want to implement all the methods at once, ok? The answer is yes. Java8 interface default method. And Google encourages us to use this approach, the DefaultLifecycleObserver

DefaultLifecycleObserver

Note: in androidx. Lifecycle. Lifecycle at the top of the class has a comment

/**
 * If you use <b>Java 8 Language</b>, then observe events with {@link DefaultLifecycleObserver}.
 * To include it you should add {@code "androidx.lifecycle:common-java8:<version>"} to your
 * build.gradle file.
 * <pre>
 * class TestObserver implements DefaultLifecycleObserver {
 *     {@literal @}Override
 *     public void onCreate(LifecycleOwner owner) {
 *         // your code
 *     }
 * }
 * </pre>
 * If you use <b>Java 7 Language</b>, Lifecycle events are observed using annotations.
 * Once Java 8 Language becomes mainstream on Android, annotations will be deprecated, so between
 * {@link DefaultLifecycleObserver} and annotations,
 * you must always prefer {@code DefaultLifecycleObserver}.
 * <pre>
 * class TestObserver implements LifecycleObserver {
 *   {@literal @}OnLifecycleEvent(ON_STOP)
 *   void onStopped() {}
 * }
 * </pre>
 * <p>
 * Observer methods can receive zero or one argument.
 * If used, the first argument must be of type {@link LifecycleOwner}.
 * Methods annotated with {@link Event#ON_ANY} can receive the second argument, which must be
 * of type {@link Event}.
 * <pre>
 * class TestObserver implements LifecycleObserver {
 *   {@literal @}OnLifecycleEvent(ON_CREATE)
 *   void onCreated(LifecycleOwner source) {}
 *   {@literal @}OnLifecycleEvent(ON_ANY)
 *   void onAny(LifecycleOwner source, Event event) {}
 * }
 * </pre>
 * These additional parameters are provided to allow you to conveniently observe multiple providers
 * and events without tracking them manually.
 */
public abstract class Lifecycle {}Copy the code

This means that annotations will be deprecated once Java 8 becomes mainstream on Android, so between DefaultLifecycleObserver and annotations, DefaultLifecycleObserver is preferred.

Use as follows

implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
Copy the code

The garage is actually a DefaultLifecycleObserver. Java interface classes. Later, when we need the LifecycleObserver, we generally implement the DefaultLifecycleObserver interface (instead of directly implementing the LifecycleObserver interface), using the following method:

class NormalActivity : Activity(), LifecycleOwner {

    private var lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(this)


    override fun getLifecycle(a): Lifecycle {
        return lifecycleRegistry
    }

    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_normal)

        lifecycle.addObserver(object : DefaultLifecycleObserver {
            // The following methods are implemented according to their own situation
            override fun onCreate(owner: LifecycleOwner){}override fun onStart(owner: LifecycleOwner){}override fun onResume(owner: LifecycleOwner){}override fun onPause(owner: LifecycleOwner){}override fun onStop(owner: LifecycleOwner){}override fun onDestroy(owner: LifecycleOwner){}})}}Copy the code

As you can see, here we simply write our logic to override the lifecycle corresponding callback method that we need. More concise.

Transitions between lifecycleObservers

When we use LifecycleObserver, the framework internally converts it to GenericLifecycleObserver or a subclass of it. The transformation behavior in class androidx. Lifecycle. Lifecycling# getCallback. As to when this method triggers, we’ll look at that later.

Now take a look at the conversion process

@NonNull
    static GenericLifecycleObserver getCallback(Object object) {
         / / if FullLifecycleObserver, converted to FullLifecycleObserverAdapter
        if (object instanceof FullLifecycleObserver) {
            return new FullLifecycleObserverAdapter((FullLifecycleObserver) object);
        }

        // If GenericLifecycleObserver, do not convert
        if (object instanceof GenericLifecycleObserver) {
            return (GenericLifecycleObserver) object;
        }

        finalClass<? > klass = object.getClass();// Get the conversion type, GENERATED_CALLBACK for code generation and REFLECTIVE_CALLBACK for reflection call
        int type = getObserverConstructorType(klass);
        if (type == GENERATED_CALLBACK) {
            // Use code generation
            List<Constructor<? extends GeneratedAdapter>> constructors =
                    sClassToAdapters.get(klass);
            // A constructor
            if (constructors.size() == 1) {
                GeneratedAdapter generatedAdapter = createGeneratedAdapter(
                        constructors.get(0), object);
                return new SingleGeneratedAdapterObserver(generatedAdapter);
            }
            // Multiple constructors
            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);
        }
        // Reflect calls by default
        return new ReflectiveGenericLifecycleObserver(object);
    }
Copy the code

The essence of this method is that based on a LifecycleObserver object passed in, Construct a GenericLifecycleObserver Object (there are four subclasses: FullLifecycleObserverAdapter, SingleGeneratedAdapterObserver, CompositeGeneratedAdaptersObserver, ReflectiveGene RicLifecycleObserver), and the resulting object contains all the information for the LifecycleObserver we created, including the various callback methods and so on.

When defining the LifecycleObserver in the form of annotations, traditionally the annotations must be resolved by reflection, which can have a performance impact. So how do you optimize?

  • By caching, you avoid getting the constructor through reflection every time.

  • Through the annotation processor, the common methods annotated by @onlifecyCleEvent are preprocessed at compile time, and the class named with “class name _LifecycleAdapter” is generated. Various callback methods are directly converted logically to avoid reflection, so as to improve performance.

Let’s take a look at how Google optimizes using only reflection

Without introducing annotation processor, Lifecycling. GetCallback (observer) returns the ReflectiveGenericLifecycleObserver

package androidx.lifecycle;
class ReflectiveGenericLifecycleObserver implements GenericLifecycleObserver {
    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

Here we focus on the code for how to get the CallbackInfo:

mInfo = ClassesInfoCache.sInstance.getInfo(mWrapped.getClass());
Copy the code

Because of the reflection of the price is relatively large, so through ClassesInfoCache again. Java the singleton class, for ReflectiveGenericLifecycleObserver class to invoke the various methods of related information in the cache.

I’ll go in and look at its getInfo(…) Inside the method, how the method information is obtained.

CallbackInfo getInfo(Class klass) {
     	// Read the cache first
        CallbackInfo existing = mCallbackMap.get(klass);
        if(existing ! =null) {
            return existing;
        }
        existing = createInfo(klass, null);
        return existing;
    }
Copy the code
private CallbackInfo createInfo(Class klass, @Nullable Method[] declaredMethods) {
    	// First extract the CallbackInfo of the parent class
    	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); }}// Retrieve the CallbackInfo of the interface
        Class[] interfaces = klass.getInterfaces();
        for (Class intrfc : interfaces) {
            for (Map.Entry<MethodReference, Lifecycle.Event> entry : getInfo(
                    intrfc).mHandlerToEvent.entrySet()) {
                VerifyAndPutHandler implements the interface or overrides the methods of the superclass, but adds different annotation events.verifyAndPutHandler(handlerToEvent, entry.getKey(), entry.getValue(), klass); }}// Finally handle the annotations of the class itselfMethod[] methods = declaredMethods ! =null ? declaredMethods : getDeclaredMethods(klass);
        boolean hasLifecycleMethods = false;
    	// Iterate through the methods, looking for the methods annotated by OnLifecycleEvent
        for (Method method : methods) {
            OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class);
            if (annotation == null) {
                continue;
            }
            hasLifecycleMethods = true;
            // Handle the number of parameters, up to two parametersClass<? >[] 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);
    	// Put it in the cache
        mCallbackMap.put(klass, info);
        mHasLifecycleMethods.put(klass, hasLifecycleMethods);
        return info;
    }
Copy the code

Here, you can see the code that handles the annotations.

Let’s look at another optimization (using annotation handlers)

First, it needs to be introduced in the project module

annotationProcessor "Androidx. Lifecycle: lifecycle - compiler: 2.0.0." "
Copy the code

When this is introduced, a file for xxx_LifecycleAdapter is automatically generated

/app/build/generated/source/apt/debug/package_name/LifeObserveCustomName_LifecycleAdapter.java

Let’s look at the effect first:

public class LifecyclePresenter implements LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    void onCreateInPresenter(@NotNull LifecycleOwner owner){
        System.out.println("on create");
    };

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    void onDestroyInPresenter(@NotNull LifecycleOwner owner){
        System.out.println("on destory");
    };

    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    void onLifecycleChangedInPresenter(@NotNull LifecycleOwner owner,
                            @NotNull Lifecycle.Event event){
        System.out.println("on any"); }}Copy the code

When the code above introduces the annotation handler, the LifecyclePresenter_LifecycleAdapter is automatically generated in the build directory when the project is compiled

public class LifecyclePresenter_LifecycleAdapter implements GeneratedAdapter {
  final LifecyclePresenter mReceiver;

  LifecyclePresenter_LifecycleAdapter(LifecyclePresenter receiver) {
    this.mReceiver = receiver;
  }

  @Override
  public void callMethods(LifecycleOwner owner, Lifecycle.Event event, boolean onAny,
      MethodCallsLogger logger) {
    booleanhasLogger = logger ! =null;
    if (onAny) {
      if(! hasLogger || logger.approveCall("onLifecycleChangedInPresenter".4)) {
        mReceiver.onLifecycleChangedInPresenter(owner,event);
      }
      return;
    }
    if (event == Lifecycle.Event.ON_CREATE) {
      if(! hasLogger || logger.approveCall("onCreateInPresenter".2)) {
        mReceiver.onCreateInPresenter(owner);
      }
      return;
    }
    if (event == Lifecycle.Event.ON_DESTROY) {
      if(! hasLogger || logger.approveCall("onDestroyInPresenter".2)) {
        mReceiver.onDestroyInPresenter(owner);
      }
      return; }}}Copy the code

Using the dependency library, these annotated methods are preprocessed at compile time and then called back directly to avoid reflection and improve performance.

Let’s look back at the Lifecycling. GetCallback (observer) method. How to determine whether the code is generated or reflected

 // Get the conversion type, GENERATED_CALLBACK for code generation and REFLECTIVE_CALLBACK for reflection call
 int type = getObserverConstructorType(klass);
 // The todo process will not be analyzed in detail
Copy the code

As we have already analyzed, the xxx_LifecycleAdapter class is generated when the annotation handler is introduced, so if we find this generation class, we assume code generation, otherwise we take a reflection call.

Let’s look at the key methods

 private static int getObserverConstructorType(Class
        klass) {
        if (sCallbackCache.containsKey(klass)) {
            return sCallbackCache.get(klass);
        }
        int type = resolveObserverCallbackType(klass);
        sCallbackCache.put(klass, type);
        return type;
    }
Copy the code
private static int resolveObserverCallbackType(Class
        klass) {
        // anonymous class bug:35073837
        // Anonymous inner classes use reflection
        if (klass.getCanonicalName() == null) {
            return REFLECTIVE_CALLBACK;
        }
		// Look for the generated class
        Constructor<? extends GeneratedAdapter> constructor = generatedConstructor(klass);
        if(constructor ! =null) {
            // To find the generated class, GENERATED_CALLBACK is used
            sClassToAdapters.put(klass, Collections
                    .<Constructor<? extends GeneratedAdapter>>singletonList(constructor));
            return GENERATED_CALLBACK;
        }

   		// Whether there are methods annotated by OnLifecycleEvent
        boolean hasLifecycleMethods = ClassesInfoCache.sInstance.hasLifecycleMethods(klass);
        if (hasLifecycleMethods) {
            // If there are methods annotated by OnLifecycleEvent, then reflect
            return REFLECTIVE_CALLBACK;
        }

    // If no generated class is found, no method is annotated by OnLifecycleEvent. We need to look at the parent class and the interface, maybe they're annotated, so we're calling again recursivelyClass<? > superclass = klass.getSuperclass(); List<Constructor<? extends GeneratedAdapter>> adapterConstructors =null;
        // If the parent class implements LifecycleObserver
    	if (isLifecycleParent(superclass)) {
            if (getObserverConstructorType(superclass) == REFLECTIVE_CALLBACK) {
                return REFLECTIVE_CALLBACK;
            }
            adapterConstructors = new ArrayList<>(sClassToAdapters.get(superclass));
        }

   			// If an interface inherits LifecycleObserver
        for(Class<? > intrface : klass.getInterfaces()) {if(! isLifecycleParent(intrface)) {continue;
            }
            if (getObserverConstructorType(intrface) == REFLECTIVE_CALLBACK) {
                return REFLECTIVE_CALLBACK;
            }
            if (adapterConstructors == null) {
                adapterConstructors = new ArrayList<>();
            }
            adapterConstructors.addAll(sClassToAdapters.get(intrface));
        }
        if(adapterConstructors ! =null) {
            sClassToAdapters.put(klass, adapterConstructors);
            return GENERATED_CALLBACK;
        }

        return REFLECTIVE_CALLBACK;
    }
Copy the code

So when we introduce the annotation handler, this will return GENERATED_CALLBACK

Lifecycling. GetCallback (observer) method will build our LifecyclePresenter object into a SingleGeneratedAdapterObserver object returns (because there’s only one constructor, If more than one constructor returns CompositeGeneratedAdaptersObserver), after mLifecycleObserver. OnStateChanged (the owner, the event); Call is actually SingleGeneratedAdapterObserver onStateChanged (the owner, the event) method:

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public class SingleGeneratedAdapterObserver implements GenericLifecycleObserver {

    private final GeneratedAdapter mGeneratedAdapter;

    SingleGeneratedAdapterObserver(GeneratedAdapter generatedAdapter) {
        mGeneratedAdapter = generatedAdapter;
    }

    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        mGeneratedAdapter.callMethods(source, event, false.null);
        mGeneratedAdapter.callMethods(source, event, true.null); }}Copy the code

And you can see here that it calls callMethods(…) of the class that’s wrapped inside. Method, the callMethonds(…) of the LifecyclePresenter_LifecycleAdapter we mentioned above Methods.

In summary, the Lifecycling. GetCallback (observer) method is easy to understand.

  1. If the object passed in isFullLifecycleObserverType, it constructed as FullLifecycleObserverAdapter object, and returns
  2. If the object passed in isGenericLifecycleObserverType, directly return the object
  3. If one or two are not satisfied, the Type of the constructor for the class (whether the class was acquired by reflection or generated by the annotation handler) is resolved. If the callback function is called from a class generated by the annotation handler, one is returnedSingleGeneratedAdapterObserver/CompositeGeneratedAdaptersObserverobject
  4. If none of the above conditions are met, each callback function is called by reflection. Returns a ReflectiveGenericLifecycleObserver object

LifecycleRegistry

Let’s go back to LifecycleRegistry

As mentioned earlier, LifecycleRegistry is a direct subclass of Lifecycle

/**
 * An implementation of {@link Lifecycle} that can handle multiple observers.
 * <p>
 * It is used by Fragments and Support Library Activities. You can also directly use it if you have
 * a custom LifecycleOwner.
 */
public class LifecycleRegistry extends Lifecycle {
    // Add a lifecycle observer (hereinafter referred to as the Observer) that will notify when the lifecycle owner state changes.
    public void addObserver(@NonNull LifecycleObserver observer) {}
    // Get the current state of the lifecycle.
    public State getCurrentState(a) {}
    // Return the number of observers.
    public int getObserverCount(a) {} 
 
    // Set the current state and notify observers.
    public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {... }// Remove the specified observer from the observer list.
    public void removeObserver(@NonNull LifecycleObserver observer) {...}
}
Copy the code

LifecycleRegistry itself is a mature Lifecycle implementation class that is instantiated for use in activities and fragments. If we need to customize the LifecycleOwner and implement an interface that needs to return an instance of Lifecycle, we can simply create a new LifecycleRegistry member in the custom LifecycleOwner and return it (in short: Directly used, the above analysis of ordinary Activity how to achieve, is directly used, you can look back at the next).

Let’s first look at a few methods for events and states

public class LifecycleRegistry extends Lifecycle {
	static State getStateAfter(Event event) {
        // This method defines Lifecycle.Event and this method defines the transition relationship between Lifecycle.State:
        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 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

Think of State as the nodes of a graph, and Event as the edges between the nodes.

States are compared according to the ordinal() value of the Enum class, which is the order in which variables are declared. Values increase in the order they are declared. As shown in the figure above, INITIALIZED state value on the left is 1, and DESTROYED state is 0 (because these two states belong to the starting and ending states, they can be regarded as the level). The RESUMED status value on the right is 4.

From left to right state change to state promotion, that is, upEvent; The status changes from right to left to downEvent. Control of the lifecycle is completed by calling the lifecycle callback by changing the state through event passing.

Let’s take a look at the most critical remaining method, the handleLifecycleEvent() method

handleLifecycleEvent()

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        State next = getStateAfter(event);
        moveToState(next);
}
Copy the code
private void moveToState(State next) {
        if (mState == next) {
            return;
        }
        mState = next;
    		// When we trigger a state change in the LifecycleRegistry callback LifecycleObserver,
        	// mHandlingEvent is true;
        	// When an observer is added, a callback method may also be executed. If a state change is triggered,
        	/ / mAddingObserverCounter! = 0
        if(mHandlingEvent || mAddingObserverCounter ! =0) {
            // Events are being processed or adding an Observer is being processed
            mNewEventOccurred = true;
            // Sync is not required.
            Sync () -> LifecycleObserver -> moveToState()
            // Return to sync() and continue synchronizing the status to the observer
            // we will figure out what to do on upper level.
            return;
        }
   		// Mark the event being processed
        mHandlingEvent = true;
    	// Sync () converts state changes into lifecycle events that are forwarded to the LifecycleObserver
        sync();
        mHandlingEvent = false;
    }
Copy the code
	/** * 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), Invariant's rule that whenever the state value of the first joined observer is greater than that of the second joined observer * this rule affects the implementation of Sync */
    private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
            new FastSafeIterableMap<>();

	private void sync(a) {
    	// Use weak applications to own LifecycleOwner, also to prevent Activity/Fragment memory leaks
        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 is for backwardPass/forwardPass() when the observer triggers a state change
            // Return in advance. We're just about to adjust them, so just set it to false.
            mNewEventOccurred = false;
            
             Invariant's rule: the state value of the first joined observer must be greater than or equal to the state value of the second joined observer
            // In the mObserverMap, the newest state is the newest, and the newest is the largest. If the current mState is less than the state value in John, the value in mObserverMap needs to be updated
            In order to maintain mObserverMap Invariant, here we need to update the state of the element from the end of the line
            if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
                 // The state of the first added observer is greater than the current state
                backwardPass(lifecycleOwner);
            }
            Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
             // If mNewEventOccurred, the customer triggered the state change when backwardPass() was called above
             // If a new event occurs, the synchronization is abandoned and delayed until the next time
            if(! mNewEventOccurred && newest ! =null
                    && mState.compareTo(newest.getValue().mState) > 0) {
                // If the state of the newly added observer is consistent, it is optimistic that the state of the observer that was added before it is consistent
                forwardPass(lifecycleOwner);
            }
        }
        mNewEventOccurred = false;
    }
Copy the code
 Return true if all observer states have been synchronized
private boolean isSynced(a) {
        if (mObserverMap.size() == 0) {
            return true;
        }
        // Eldest is newest
        State eldestObserverState = mObserverMap.eldest().getValue().mState;
        State newestObserverState = mObserverMap.newest().getValue().mState;
    	// Since we guarantee that the state of the header is >= the state of the elements following the header, we only need to judge the header and the end
    	return eldestObserverState == newestObserverState && mState == newestObserverState;
    }
Copy the code

The main purpose of sync() is to synchronize the state of all elements in the mObserverMap to mState.

If a backward state is required, and if a forward state is required, the code for backward is as follows:

 private void backwardPass(LifecycleOwner lifecycleOwner) {
        // Use the younger (start) to determine if a fallback is needed
        // End -> start
        Iterator<Entry<LifecycleObserver, ObserverWithState>> descendingIterator =
                mObserverMap.descendingIterator();
        while(descendingIterator.hasNext() && ! mNewEventOccurred) {// mNewEventOccurred determines whether a new event has been distributed
            Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();
            ObserverWithState observer = entry.getValue();
            while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred
                    && mObserverMap.contains(entry.getKey()))) {
                / / back to back
           		For example, observer.state is RESUMED
            	/ / mState is CREATED
            	/ / downEvent (observer. State) for ON_PAUSE
                Event event = downEvent(observer.mState);
                / / getStateAfter (event) is STARTED
            	// Finally: RESUMED -> STARTED, when the next synchronization is RESUMED as CREATED
            	// pushParentState and popParentState temporarily save the state in the List
                // We'll talk about this in addObserver
                pushParentState(getStateAfter(event));
                 // Distribute eventsobserver.dispatchEvent(lifecycleOwner, event); popParentState(); }}}Copy the code

As you look at this method, you can refer to the state diagram above. For example, suppose all the elements in the current queue are CREATED. It then receives an ON_START event. As you can see from the diagram, it should then go to the STARTED state. Since STARTED is greater than CREATED, forwardPass() is executed. ForwardPass () calls upEvent(observer.mstate), which returns the event to be sent from CREATED to STARTED, namely ON_START. The ON_START event is sent to the customer.

Also note that the logic of backwardPass() is to gradually roll back large states. Why step by step? For example, if observer.state is RESUMED, and the current state is CREATED, there are two rollback steps: RESUMED -> STARTED and STARTED -> CREATED

ForwardPass () has similar logic, so we won’t analyze it.

As you can see in the figure above, an ObserverWithState observer object is finally obtained through mObserverMap and its dispatchEvent is called for event distribution

Moving on to ObserverWithState, which is a static inner class of LifecycleRegistry.

static class ObserverWithState {
        State mState;
        GenericLifecycleObserver mLifecycleObserver;

        ObserverWithState(LifecycleObserver observer, State initialState) {
            //getCallback is used to transform the LifecycleObserver for detailed analysis above
            mLifecycleObserver = Lifecycling.getCallback(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 the name suggests, this class encapsulates both an Observer object and a State object (specifically State and GenericLifecycleObserver, GenericLifecycleObserver is an interface, Inherited from LifecycleObserver), in its dispatchEvent method, will eventually call back to the mLifecycleObserver’s onStateChanged(…) Methods.

Tracing this point, Lifecycle will eventually call back to the GenericLifecycleObserver# onStateChanged() method after listening for Lifecycle changes.

Let’s go through the process here (for example, Fragment).

  1. Fragment implements the LifecycleOwner interface and provides a LifecycleRegistry instance

  2. In each life cycle, fragments of call LifecycleRegistry. HandleLifecycleEvent distributed life cycle event (event) method

  3. LifecycleRegistry. HandleLifecycleEvent (event) from ObserverWithState mObserverMap removed in all kinds of synchronous operation, in the process of synchronization, The ObserverWithState#dispatchEvent method is called to distribute the lifecycle event

  4. The handleLifecycleEvent method retrieves the next state from the current state via getStateAfter, and then changes the current state value using the moveToState method. We then call the sync method to notify the LifecycleObserver, the class where we implemented the LifecycleObserver interface

    In the sync method, the current State is updated by comparing the current State with the previous State. In the forwardPass and backwardPass methods, the ObserverWithState elements are extracted from the mObserverMap and synchronized one by one. In the synchronization you’ll see the event dispatch method, the dispatchEvent method of the ObserverWithState inner class.

Now there is only one question left, how do the elements in the mObserverMap store in, I have looked at the mObserverMap call, there is only one place, that is the addObserver method

@Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        // ...
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
		// ...
    }
Copy the code

And that’s exactly what we’re calling in the Fragment

getLifecycle().addObserver(mObserver);

At this point, we are finally connected to our MyObserver and the entire process is connected.

Finally, take a look at the addObserver method

addObserver

@Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        // The todo comment should be understood again
        PushParentState and popParentState before and after dispatchEvent are used to solve this problem:
        // If an onStart observer is registered and unregistered, the state of the newly registered observer is INITIALIZED;
        // If you want to perform a callback to ON_START, you need newObserver to be in the CREATED state (the former state does not exist in mObserverMap because of removeObserver).
       // mParentStates creates this status for newObserver

    
        // If they are not DESTROYED, the deployment starts from INITIALIZED
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        // ObserverWithState is used to distribute events to observers
        // ObserverWithState will do the Observer conversion
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        // Put it in the map
        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;
        }

        // isReentrance indicates whether an observer has been added to the event distribution
    	// For example: in the observer, addObserver() is called again in onStart()
        booleanisReentrance = mAddingObserverCounter ! =0 || mHandlingEvent;
        // The parentState, targetState, and so on are introduced to ensure that the state of the following Observer in the list is not greater than that of the preceding one. After doing this, if the first and last state of the list are equal to LifecycleRegistry. State synchronization is complete.
        // Calculate the state to be distributed
        State targetState = calculateTargetState(observer);
        mAddingObserverCounter++;
        // Distribute events to targetState
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            Statefulobserver. state is smaller than targetState
            pushParentState(statefulObserver.mState);
            // If state is STARTED, then upEvent(state) is ON_RESUME
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();
            // mState / subling may have been changed recalculate
            targetState = calculateTargetState(observer);
        }

        //addObserver() mainly considers the case of Reentrance, that is, adding a new observer to the event distribution of the observer.
        if(! isReentrance) {// we do sync only on the top level.
             // If the current entry is reentrant, no synchronization will be performed
            sync();
        }
        mAddingObserverCounter--;
    }
Copy the code
private State calculateTargetState(LifecycleObserver observer) {
     	// Get the last observer that was addedEntry<LifecycleObserver, ObserverWithState> previous = mObserverMap.ceil(observer); State siblingState = previous ! =null ? previous.getValue().mState : null;
    	// mParentStates is a List, which is added and removed by pushParentState() and popParentState(), respectively, in pairs, before and after the dispatchEvent
    	// In this case, parentState will exist: when dispatchEvent is used, addObserver() will be called, i.e. isReentrance aboveState parentState = ! mParentStates.isEmpty() ? mParentStates.get(mParentStates.size() -1)
                : null;
    	// The calculation here is to get a more appropriate state
    	// Consider the following cases: If an observer calls addObserver in onStart(), the observer should be distributed in the STARTED state, and the current state, mState, could be RESUMED in sync()
        return min(min(mState, siblingState), parentState);
    }
Copy the code

Rather than simply adding an Observer to a map, addObserver first does the Observer transformation mentioned above. The second thing to consider is the reentry problem. The so-called “reentrant problem” is that addObserver will trigger calls to Observer lifecycle functions, and the Observer in turn calls methods such as addObserver. Thus, LifecycleRegistry uses the variables mAddingObserverCounter and mHandlingEvent to determine if you are in the reentrant state.

Other LifecycleOnwer

LifecycleService

ServiceLifecycleDispatcher distributed the event back to the main thread message queue, to guarantee to ensure the callback after the Service lifecycle callback to call again.

ProcessLifecycleOwner

It is used to listen for the entire application to switch between front and back. Also use ActivityLifecycleCallback to monitor each Activity life cycle, if the onStop incident, not listening to any onStart events, The ProcessLifecycleOwner will assume that the entire application is switched to the background while leaving a flag. If you listen for the onStart event and you check for flags then the application is considered to be back in the foreground.

Juejin. Cn/post / 5 d15bb…

Linxiaotao. Making. IO / 2019/01/14 /…

Use ProcessLifecycle to gracefully listen for todo transitions between front and back of the application

other

The following paragraph of todo can be put in another article

Best practices for lifecycle aware components

  • Try to keep your UI controllers (activities and fragments) from carrying everything on their own. Instead of trying to get their own data, they should react to changes on the view by looking at the ViewModel and a LiveData object.
  • Try writing a data-driven UI and making your UI controller responsible for updating the view when data changes or notifying the ViewModel of user behavior.
  • Put your data logic into the ViewModel class. The ViewModel should act as the connection between your UI controller and the rest of your application. Be careful: It is not the ViewModel’s responsibility to get the data (such as downloading it from the network), rather, the ViewModel should call the appropriate component to get the data and then provide the results to the UI controller.
  • Use data binding to maintain a clean interface between your view and your UI controller. This helps to make your views more declarative and allows you to add minimal update logic to the UI controller. If you prefer to use the Java language for data binding, using a library such as Butter Knife can avoid octet code for better abstraction.
  • If your UI is complex, consider creating a Presenter class to handle UI changes. This can be tiring, but it makes your UI components easier to test.
  • Avoid in yourViewModelDirect reference inViewActivitySuch as the context. ifViewModelOutlive its activity (such as configuration changes), and your activity is leaking memory and hard to recycle properly by GC.

Use cases for lifecycle aware components

Lifecycle aware components make life cycle management easy in many use cases. Here are a few examples:

  • Toggles the accuracy of geolocation updates. Launch high-precision geolocation updates when your application is visible; When your application goes into the background, switch to low-precision updates. LiveData is a lifecycle aware component that allows your application to automatically update the UI as the user moves.
  • Start and stop video buffering. Start video buffering as soon as possible, but delay playback until the app is fully started. You can also use such a component to stop the video buffering when the application is destroyed.
  • Start and stop network connections. When the application is in the foreground, enable streaming media using network connection; Automatically pause when the application is in the background.
  • Pause and resume animation drawable. Handle the pause of the animation drawable when the application enters the background; When the application returns to the foreground, restore the animation.

Handle the onStop event

When Lifecycle belongs to an AppCompatActivity or Fragment, Lifecycle’s state becomes CREATED, The ON_STOP event is distributed when onSaveInstanceState() of AppCompatActivity or Fragment is called.

When a Fragment or AppCompatActivity’s state is saved in onSaveInstanceState(), its UI is considered untouchable until ON_START is triggered. Trying to change the UI after the state has been saved can cause your application to have an inconsistent navigational state, which is why the FragmentManager throws an exception when the application tries to execute a FragmentTransaction after the state has been saved. For more information, see Commit ().

LiveData provides out-of-the-box support for this edge case: if the observer is associated with a Lifecycle that is not even STARTED, it will not call the observer. Its internal implementation first calls isAtLeast() to decide whether to trigger its observer.

Sadly, AppCompatActivity’s onStop() is called after onSaveInstanceState(), which results in a gap where the UI is not allowed to change but Lifecycle has not yet entered the CREATED state.

To prevent such a tragedy, Lifecycle in beta2 and later marks the state as CREATED but does not distribute events so that any code that checks the current state will get the real value even though the events are not distributed until the system call onStop().

The secondary tragedy is that there are two main problems with this solution:

  • At API versions 23 and below, Android actually saves an activity’s state even if it is partially blocked by another activity. In other words, the Android system calls onSaveInstanceState(), but not necessarily onStop(). This leads to a potentially long gap during which the observer still thinks the lifecycle is active, but the UI state cannot be changed.
  • Anyone who wants to expose such behavior toLiveDataAll classes need to be implementedbeta2Or laterLifecycleThe workarounds provided.

Note: To make this process easier and more backward compatible, beginning with 1.0.0-rc1 Lifecycle objects will be marked as CREATED, ON_STOP is distributed when onSaveInstanceState() is called, without waiting for the onStop method to be called. This shouldn’t affect your code much, but you still need to be aware of it, because it doesn’t match the order in which Activity methods are called in the API version 26 and later.

The above is a translation from the official document. See reference 1 for the translation address.

reference

Use lifecycle aware components to handle the lifecycle

Learning about Lifecycle

A detailed analysis of the official Android architecture component Lifecycle

The Jetpack Lifecycle

Android Arch Components source code Analysis (2) — Lifecycle

Android Architecture Component — Lifecycle Analysis

Lifecycle Source code Parsing (1)

Lifecycle source code Parsing (part 2)

The Beauty of the Android architecture -Lifecycle