For those who are not familiar with the LifeCycle component, read this article:

A detailed explanation of Jetpack’s LifeCycle component

Learning problems

  1. How does LifeCycle listen to changes in the Activity/Fragment LifeCycle?

  2. How does LifeCycle distribute events that change during the LifeCycle to observers?

This article directory

One or four important classes

(a) Lifecycle

Lifecycle is an abstract class. It defines two enumerations internally: Event the type of Event to be distributed, and State the State of the host.

1.Event

public enum Event {
    // The onCreate method corresponding to the host (the class that implements LifecycleOwner)
    ON_CREATE,
        
    // The onStart method corresponding to the host (the class that implements LifecycleOwner)
    ON_START,
        
    // The onResume method corresponding to the host (the class that implements LifecycleOwner)
    ON_RESUME,
        
    // The onPause method corresponding to the host (the class that implements LifecycleOwner)
    ON_PAUSE,
        
    // The onStop method corresponding to the host (the class that implements LifecycleOwner)
    ON_STOP,
        
    // The onDestroy method corresponding to the host (the class implementing LifecycleOwner)
    ON_DESTROY,
        
    // Can match all life cycle events of the host
    ON_ANY
}
Copy the code

Timing of distribution of each lifecycle event:

ON_CREATE, ON_START, and ON_RESUME: These three lifecycle events are distributed after the execution of the host’s corresponding lifecycle method has completed.

ON_PAUSE, ON_STOP, and ON_DESTROY: These three lifecycle events are distributed before the host’s corresponding lifecycle method is called.

2.State

public enum State {

    // Destroyed state. In the case of an Activity, the host reaches this state before calling back the Activity's onDestroy method.
    DESTROYED,

    // Initialized state. A state before the callback to the onCreate method.
    INITIALIZED,

    // The state has been created. There are two ways to be in this state:
    //1. After the host's onCreate method is executed
    //2. Before the host's onStop method is called
    CREATED,

    // Visible state. There are two ways to be in this state:
    //1. After the host's onStart method is executed
    //2. Before the host's onPause method is called
    STARTED,

    // Focus (interactive state). The host is in this state after executing the onResume method.
    RESUMED;

    public boolean isAtLeast(@NonNull State state) {
        return compareTo(state) >= 0; }}Copy the code

3. Mapping between Event and State

(2) LifecycleRegistry

It is the only implementation class for Lifecycle. It is primarily used to register observers (LifecycleObservers) and distribute host state to them (multiple observers can be handled).

(3) LifecycleOwner

To declare that it is a host for lifecycle events, both activities and fragments implement this interface. There is only one getLifecycle method internally.

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

(4) LifecycleObserver

Used to define an observer.

The relationship between the four classes

Description:

  1. Activities/fragments both implement the LifecycleOwner interface by default;
  2. LifecycleRegistry is Lifecycle’s only implementation class;
  3. There are three ways to implement an Observer:
    • LifecycleObserver is annotated with @onlifecyCleEvent
    • DefaultLifecycleObserver hosts all life cycle events
    • LifecycleEventObserver encapsulates host Lifecycle events as lifecyc.event
  4. Pass in an Activity/FragmentgetLifecycle()Method to get a LifecycleRegistry object;
  5. By calling the LifecycleRegistry objectaddObserver()Add an observer (which can be implemented in any of the three ways).

3. How to implement LifyCycle in fragments

LifecycleRegistry is used to distribute events within each lifecycle method of the Fragment.

public class Fragment implements LifecycleOwner {

    LifecycleRegistry mLifecycleRegistry;

    void performCreate(Bundle savedInstanceState) {
        onCreate(savedInstanceState);
        // The ON_CREATE event is distributed after the onCreate method is executed
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
    }

    void performStart(a) {
        onStart();
        // The ON_START event is distributed after the onStart method is executed
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
    }

    void performResume(a) {
        onResume();
        // The ON_RESUME event is distributed after the onResume method has been executed
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
    }

    void performPause(a) {
        // The ON_PAUSE event is distributed before the execution of the onPause method
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
        onPause();
    }

    void performStop(a) {
        // The ON_STOP event is distributed before the execution of the onStop method
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
        onStop();
    }

    void performDestroy(a) {
        // The ON_DESTROY event is distributed before the execution of the onDestroy methodmLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY); onDestroy(); }}Copy the code

4. How to implement LifyCycle for Activity

An Activity implementing Lifecycle requires adding a Fragment to the Activity using the ReportFragment. The ReportFragment does not have any pages and is only responsible for distributing events using LifecycleRegistry when the lifecycle changes.

The ReportFragment is needed to accommodate scenarios that are not inherited from AppCompactActivity, and also to support our custom LifecycleOwner scenarios.

(a) ComponentActivity source analysis

The following is the source code for ComponentActivity, in the onCreate method to add a fragment inside the Activity.

public class ComponentActivity extends Activity implements LifecycleOwner {
  
    private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

    @SuppressLint("RestrictedApi")
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Add a fragment
        ReportFragment.injectIfNeededIn(this); }}Copy the code

Add an inheritance to the Activity:

(2) Source analysis of ReportFragment

Let’s take a look at the ReportFragment source code. InjectIfNeededIn is the main method in the ReportFragment.

public class ReportFragment extends Fragment {...public static void injectIfNeededIn(Activity activity) {
        / / 1. If the API > = 29, registered ActivityLifecycleCallbacks
        if (Build.VERSION.SDK_INT >= 29) {
            activity.registerActivityLifecycleCallbacks(
                    new LifecycleCallbacks());
        }

        //2. Add ReportFragment to the Activity
        android.app.FragmentManager manager = activity.getFragmentManager();
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(newReportFragment(), REPORT_FRAGMENT_TAG).commit(); manager.executePendingTransactions(); }}...Copy the code

The injectIfNeededIn method does two things:

1. Determine the current API Level and select the time and mode to listen for the Activity lifecycle based on the API Level

(1) API Level >= 29

If greater than or equal to 29, will register a ActivityLifecycleCallbacks,

if (Build.VERSION.SDK_INT >= 29) {
    activity.registerActivityLifecycleCallbacks(new LifecycleCallbacks());
}
Copy the code

ActivityLifecycleCallbacks is the Application of an internal interface.

public interface ActivityLifecycleCallbacks {
        void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState);
        void onActivityStarted(@NonNull Activity activity);
        void onActivityResumed(@NonNull Activity activity);
        void onActivityPaused(@NonNull Activity activity);
        void onActivityStopped(@NonNull Activity activity);
        void onActivityDestroyed(@NonNull Activity activity);
    }
Copy the code

To the Activity’s onResume () life cycle as an example, if we register the ActivityLifecycleCallbacks, The Android system will first callback ActivityLifecycleCallbacks onActivityResumed method, then the implementation of the Android itself onResume () method.

Using this feature, we can register a custom ActivityLifecycleCallbacks, add custom on the ActivityLifecycleCallbacks distribution, the logic of life cycle events to notify observers:

public class ReportFragment extends Fragment {

    public static void injectIfNeededIn(Activity activity) {
        if (Build.VERSION.SDK_INT >= 29) {
            activity.registerActivityLifecycleCallbacks(
                    new LifecycleCallbacks());
        }
        
        android.app.FragmentManager manager = activity.getFragmentManager();
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(newReportFragment(), REPORT_FRAGMENT_TAG).commit(); manager.executePendingTransactions(); }}@SuppressWarnings("deprecation")
    static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) {...if (activity instanceof LifecycleOwner) {
            Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
            if (lifecycle instanceof LifecycleRegistry) {
                // LifecycleRegistry is ultimately used to handle event distribution((LifecycleRegistry) lifecycle).handleLifecycleEvent(event); }}}/ / custom ActivityLifecycleCallbacks to handle life cycle events distribution, notify the observer
    static class LifecycleCallbacks implements Application.ActivityLifecycleCallbacks {...@Override
        public void onActivityPostCreated(@NonNull Activity activity,
                @Nullable Bundle savedInstanceState) {
            // Distribute the ON_CREATE event
            dispatch(activity, Lifecycle.Event.ON_CREATE);
        }

        @Override
        public void onActivityPostStarted(@NonNull Activity activity) {
            // Distribute the ON_START event
            dispatch(activity, Lifecycle.Event.ON_START);
        }

        @Override
        public void onActivityPostResumed(@NonNull Activity activity) {
            // Distribute the ON_RESUME event
            dispatch(activity, Lifecycle.Event.ON_RESUME);
        }

        @Override
        public void onActivityPrePaused(@NonNull Activity activity) {
            // Distribute the ON_PAUSE event
            dispatch(activity, Lifecycle.Event.ON_PAUSE);
        }

        @Override
        public void onActivityPreStopped(@NonNull Activity activity) {
            // Distribute the ON_STOP event
            dispatch(activity, Lifecycle.Event.ON_STOP);
        }

        @Override
        public void onActivityPreDestroyed(@NonNull Activity activity) {
            // Distribute the ON_DESTROY eventdispatch(activity, Lifecycle.Event.ON_DESTROY); }... }}Copy the code

(2) API Level < 29

If the API is less than 29, the implementation is the same as the Fragment implementation, using LifecycleRegistry to distribute the corresponding Lifecycle.Event events to each observer within each Lifecycle method:

public class ReportFragment extends Fragment {

    public static void injectIfNeededIn(Activity activity) {
        if (Build.VERSION.SDK_INT >= 29) {
            activity.registerActivityLifecycleCallbacks(
                    new LifecycleCallbacks());
        }
        
        android.app.FragmentManager manager = activity.getFragmentManager();
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(newReportFragment(), REPORT_FRAGMENT_TAG).commit(); manager.executePendingTransactions(); }}@Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        dispatch(Lifecycle.Event.ON_CREATE);
    }

    @Override
    public void onStart(a) {
        super.onStart();
        dispatch(Lifecycle.Event.ON_START);
    }

    @Override
    public void onResume(a) {
        super.onResume();
        dispatch(Lifecycle.Event.ON_RESUME);
    }

    @Override
    public void onPause(a) {
        super.onPause();
        dispatch(Lifecycle.Event.ON_PAUSE);
    }

    @Override
    public void onStop(a) {
        super.onStop();
        dispatch(Lifecycle.Event.ON_STOP);
    }

    @Override
    public void onDestroy(a) {
        super.onDestroy();
        dispatch(Lifecycle.Event.ON_DESTROY);
    }

    private void dispatch(@NonNull Lifecycle.Event event) {
        // Check the API here to avoid duplicating events
        if (Build.VERSION.SDK_INT < 29) { dispatch(getActivity(), event); }}}Copy the code

InjectIfNeededIn creates a ReportFragment and adds it to the Activity

public class ReportFragment extends Fragment {
    
    public static void injectIfNeededIn(Activity activity) {...// Add a ReportFragment to the Activity
        android.app.FragmentManager manager = activity.getFragmentManager();
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(newReportFragment(), REPORT_FRAGMENT_TAG).commit(); manager.executePendingTransactions(); }}}Copy the code

Five, LifecycleRegistry source code analysis

In the previous analysis, we saw how activities/fragments implement LifeCycle. LifecycleRegistry ultimately handles the distribution of LifeCycle events. Therefore, We have a comparative look at the inner workings of LifecycleRegistry.

(a) addObserver() source code analysis

LifeCycle is implemented through the observer pattern. Adding an observer is done by calling the addObserver() method:

getLifecycle().addObserver(observer);
Copy the code

Let’s look at the complete addObserver() method:

public void addObserver(@NonNull LifecycleObserver observer) {
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

        if(previous ! =null) {
            return;
        }
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            // it is null we should be destroyed. Fallback quickly
            return;
        }

        booleanisReentrance = mAddingObserverCounter ! =0 || mHandlingEvent;
        State targetState = calculateTargetState(observer);
        mAddingObserverCounter++;
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();
            // mState / subling may have been changed recalculate
            targetState = calculateTargetState(observer);
        }

        if(! isReentrance) {// we do sync only on the top level.
            sync();
        }
        mAddingObserverCounter--;
    }
Copy the code

Here’s a line by line analysis:

1. First determine the initialization status of the newly added Observer

State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
Copy the code

As long as the current host state is not DESTROYED, its initial state is INITIALIZED.

2. Wrap the Observer as ObserverWithState

ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
Copy the code

ObserverWithState represents an Observer with state. This class will be examined in more detail later.

3. Add the Observer to the collection

ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

if(previous ! =null) {
    return;
}
Copy the code

Add ObserverWithState to the collection using the putIfAbsent() method. If you have added it before, the putIfAbsent() method will return the ObserverWithState directly. In this case, the program will return directly.

4. Use a while loop to align the observer and host states

// First calculate the state the observer should be in
State targetState = calculateTargetState(observer);
// Compare the observer's state to the host's current state using the compareTo method. If the state is less than 0, the two states are not aligned
while ((statefulObserver.mState.compareTo(targetState) < 0
        && mObserverMap.contains(observer))) {
    pushParentState(statefulObserver.mState);
    // Perform an event distribution
    statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
    popParentState();
    // The next state that the observer should be in is calculated, and the observer state will be compared to it in the next loop until the states align and exit the loop
    targetState = calculateTargetState(observer);
}
Copy the code

Using the logic of the while loop, we can conclude:

Registered observers in any lifecycle method of an Activity/Fragment receive full lifecycle events.

For example, we register observers in the onResume() method:

  • While first loop: distributes on_Create event, observer state INITIALIZED -> CREATED
  • While second loop: distribute on_Start event, observer status CREATED -> STARTED
  • While third loop: distribute on_Resume event, observer state STARTED -> RESUMED

However, it is best to register in the onCreate method.

Refer to the article for comparing two enumeration values using compareTo:

Java enumeration comparison

(2) handleLifecycleEvent() source analysis

The handleLifecycleEvent() method is primarily responsible for the corresponding event distribution when the host lifecycle changes.

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        State next = getStateAfter(event);
        moveToState(next);
    }
Copy the code

1. First, according to the event that needs to be distributed, what state is the host in

Assuming that the ON_START event is being distributed, the host is currently in the STARTED state according to the getStateAfter() method.

static State getStateAfter(Event event) {
        switch (event) {
            case ON_CREATE:
            case ON_STOP:
                return CREATED;
            case ON_START:
            case ON_PAUSE:
                return STARTED;
            case ON_RESUME:
                return RESUMED;
            case ON_DESTROY:
                return DESTROYED;
            case ON_ANY:
                break;
        }
Copy the code

2. Set the current host state according to the host state obtained in step 1 and notify the observer

private void moveToState(State next) {
        if (mState == next) {
            return;
        }
        // Set the current statemState = next; .// Notify the observer
        sync();
    }
Copy the code

Let’s look at the sync method:

private void sync(a) {
        
    while(! isSynced()) {// If the current state of the host is less than the state of the first observer added to the mObserverMap set
        // The host may fall back to the RESUMED state. For example, if the host is RESUMED, onPause falls back to the STARTED state
        // backwardPass is called to distribute an on_PAUSE event to each observer in the collection and synchronize its state.
        if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
            backwardPass(lifecycleOwner);
        }

        // If the current state of the host is greater than the state of the first observer added to the mObserverMap set
        // The host may have advanced to a RESUMED state. For example, if the host is in the STARTED state, the host RESUMED to a RESUMED state
        // Call forwardPass to distribute an on_Resume event to each observer in the collection and synchronize its state.
        Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
        if(! mNewEventOccurred && newest ! =null
                && mState.compareTo(newest.getValue().mState) > 0) {
            forwardPass(lifecycleOwner);
        }
    }
    mNewEventOccurred = false;
}
Copy the code

(3) Analysis of ObserverWithState source code

ObserverWithState is the inner class in LifecycleRegistry that holds the observer and its state.

static class ObserverWithState {
    State mState;
    LifecycleEventObserver mLifecycleObserver;

    // ADAPTS the incoming LifecycleObserver to LifecycleEventObserver in order to unify the distribution of events.
    // In the previous article, we explained that there are three types of implementation observer, each of which receives a different type of event. If you do not uniformly distribute the event, it can become cumbersome
    ObserverWithState(LifecycleObserver observer, State initialState) {
        mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
        mState = initialState;
    }

    void dispatchEvent(LifecycleOwner owner, Event event) {
        State newState = getStateAfter(event);
        mState = min(mState, newState);
        // Perform event distributionmLifecycleObserver.onStateChanged(owner, event); mState = newState; }}Copy the code

6. Reference materials

Official Google Jetpack documentation

Moocs: Learn Jetpack from an architect

The Android Jetpack App Guide by Ye Kun