PS: the original text was first published on wechat official account: Jingxing zhi (Jzman-blog)

Lifecycle-Aware component is part of Android Jetpack that can sense changes in Activity and Fragment Lifecycle states, making it easier to organize, lightweight, and maintainable code. A common development approach is to deal with the business logic in the lifecycle of the component. This approach leads to bad code and bugs. Lifecycle components can be used to remove the component-dependent code from the lifecycle and move it into the component itself.

Lifecycle

Lifecycle is an abstract class that holds information about the Lifecycle state of a component. Its direct subclass is LifecycleRegistry. Both activities and Fragments implement the LifecycleOwner interface indirectly. LifecycleRegistry (Lifecycle) Lifecycle (Lifecycle) is Lifecycle (Lifecycle) and Lifecycle (Lifecycle) is Lifecycle (Lifecycle).

There are two main points in the diagram: events and Status.

  • Event: life cycle methods corresponding to activities or fragments, such as ON_CREATE and ON_START
  • Status: The state that Lifecycle is in. The next state to ON_CREATE and ON_STOP in the figure above is CREATED.

If the development environment is Java1.7, you can use annotations to listen for lifecycle changes as follows:

/** * Powered by jzman. * Created on 2018/12/8 0008. */
public class LifeCycleListener implements LifecycleObserver {

    private static final String TAG = LifeCycleListener.class.getSimpleName();

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    private void onCreate(LifecycleOwner owner) {
        Log.i(TAG,"--onCreate-->");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    private void onStart(LifecycleOwner owner) {
        Log.i(TAG,"--onStart-->");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    private void onResume(LifecycleOwner owner) {
        Log.i(TAG,"--onResume-->");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    private void onPause(LifecycleOwner owner) {
        Log.i(TAG,"--onPause-->");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    private void onStop(LifecycleOwner owner) {
        Log.i(TAG,"--onStop-->");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    private void onDestroy(LifecycleOwner owner) {
        Log.i(TAG,"--onDestroy-->");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    private void onAny(LifecycleOwner owner, Lifecycle.Event event) {
        The onAny method can add a second parameter to get the current life cycle
        // Any life cycle state change is triggered
        Log.i(TAG,"--onAny-->"+event.name()); }}Copy the code

If the development environment is Java1.8, it is recommended to listen for lifecycle changes by implementing the DefaultLifecycleObserver interface, first in the build.gradle file of the corresponding module:

implementation "Android. Arch. Lifecycle: common - java8:1.1.1"
Copy the code

Then, create a lifecycle listener as follows:

/** * Powered by jzman. * Created on 2018/12/10 0010. */
public class LifeCycleListener1 implements DefaultLifecycleObserver {

    private static final String TAG = LifeCycleListener.class.getSimpleName();

    @Override
    public void onCreate(@NonNull LifecycleOwner owner) {
        Log.i(TAG,"--onCreate-->");
    }

    @Override
    public void onStart(@NonNull LifecycleOwner owner) {
        Log.i(TAG,"--onStart-->");
    }

    @Override
    public void onResume(@NonNull LifecycleOwner owner) {
        Log.i(TAG,"--onResume-->");
    }

    @Override
    public void onPause(@NonNull LifecycleOwner owner) {
        Log.i(TAG,"--onPause-->");
    }

    @Override
    public void onStop(@NonNull LifecycleOwner owner) {
        Log.i(TAG,"--onStop-->");
    }

    @Override
    public void onDestroy(@NonNull LifecycleOwner owner) {
        Log.i(TAG,"--onDestroy-->"); }}Copy the code

Finally, register the listener in the corresponding Activity or Fragment as follows:

LifeCycleListener mLifeCycleListener = new LifeCycleListener();
getLifecycle().addObserver(mLifeCycleListener);
Copy the code

LifeCycleListener is used as an example. Lifecycle listens to Activity Lifecycle run logs as follows:

/ / open the Activity
 --onCreate-->
--onAny-->ON_CREATE
--onStart-->
--onAny-->ON_START
--onResume-->
--onAny-->ON_RESUME
/ / out of the Activity
--onPause-->
--onAny-->ON_PAUSE
--onStop-->
--onAny-->ON_STOP
--onDestroy-->
--onAny-->ON_DESTROY
Copy the code

Lifecycle source analysis

LifecycleOwner is an interface that indicates that the class implementing the interface has a lifecycle, for example all activities that inherit from AppCompatActivity indirectly implement the LifecycleOwner interface. Source code is ComponentActivity implementation of the interface, the actual development can realize LifecycleOwner interface to the original Activity or Fragment lifecycle execution of the business to the component itself.

Use getLifecycle() to get LifecycleRegistry objects that are Lifecycle implementation classes. Then use addObserver to add LifecycleObserver objects. Add an observer to be notified, and then the observer will be notified when the Activity or Fragment life cycle changes.

ComponentActivity add an unbounded Fragment to sense the life cycle of the Activity, source code as follows:

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mSavedStateRegistryController.performRestore(savedInstanceState);
    // Add a Fragment to the Activity
    ReportFragment.injectIfNeededIn(this);
}
Copy the code

InjectIfNeededIn creates a ReportFragment Fragment that is added to the corresponding Activity every time an Activity is created. ReportFragment source:

public class ReportFragment extends Fragment {
    
    / / create fragments
    public static void injectIfNeededIn(Activity activity) {
        android.app.FragmentManager manager = activity.getFragmentManager();
        // Ensure to add once
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(newReportFragment(), REPORT_FRAGMENT_TAG).commit(); manager.executePendingTransactions(); }}/ /...

    // The Activity initializes a listener to listen for the Activity's lifecycle status
    private ActivityInitializationListener mProcessListener;

    // Activity Lifecycle state distribution
    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);
        // Distribute the corresponding lifecycle status
        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;
    }

    // Distribute the lifecycle state
    private void dispatch(Lifecycle.Event event) {
       // LifecycleRegistryOwner has been deprecated, save should be for compatibility
        Activity activity = getActivity();
        if (activity instanceof LifecycleRegistryOwner) {
            ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
            return;
        }
        
        // Get Lifecycle in the Activity
        if (activity instanceof LifecycleOwner) {
            Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
            if (lifecycle instanceof LifecycleRegistry) {
                // Distribute the Activity lifecycle state((LifecycleRegistry) lifecycle).handleLifecycleEvent(event); }}}void setProcessListener(ActivityInitializationListener processListener) {
        mProcessListener = processListener;
    }
    
    // The Activity initializes the listener
    interface ActivityInitializationListener {
        void onCreate(a);

        void onStart(a);

        void onResume(a); }}Copy the code

The dispatch process corresponds to the Dispatch method, which calls the handleLifecycleEvent method. This method will be described later. One of the Activity corresponding to the life cycle of listening is done in the middle of ActivityInitializationListener, check the interface implementation class is in an anonymous inner class, located in ProcessLifecycleOwner, source code is as follows:

public class ProcessLifecycleOwner implements LifecycleOwner {
    // ...
    
    private Handler mHandler;
    private final LifecycleRegistry mRegistry = new LifecycleRegistry(this);

    private Runnable mDelayedPauseRunnable = new Runnable() {
        @Override
        public void run(a) { dispatchPauseIfNeeded(); dispatchStopIfNeeded(); }};/ / ActivityInitializationListener anonymous implementation class
    private ActivityInitializationListener mInitializationListener =
            new ActivityInitializationListener() {
                @Override
                public void onCreate(a) {
                    / / what?
                    // Why no processing, does not affect the reading of the source
                }

                @Override
                public void onStart(a) {
                    activityStarted();
                }

                @Override
                public void onResume(a) { activityResumed(); }};private static final ProcessLifecycleOwner sInstance = new ProcessLifecycleOwner();

    // where is the initialization done? - > see later
    static void init(Context context) {
        sInstance.attach(context);
    }

    void activityStarted(a) {
        mStartedCounter++;
        if (mStartedCounter == 1 && mStopSent) {
            // Whether ON_START or ON_RESUME, the key is the handleLifecycleEvent method
            mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
            mStopSent = false; }}void activityResumed(a) {
        mResumedCounter++;
        if (mResumedCounter == 1) {
            if (mPauseSent) {
                mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
                mPauseSent = false;
            } else{ mHandler.removeCallbacks(mDelayedPauseRunnable); }}}void activityPaused(a) {
        mResumedCounter--;
        if (mResumedCounter == 0) { mHandler.postDelayed(mDelayedPauseRunnable, TIMEOUT_MS); }}void activityStopped(a) {
        mStartedCounter--;
        dispatchStopIfNeeded();
    }
    private void dispatchPauseIfNeeded(a) {
        if (mResumedCounter == 0) {
            mPauseSent = true; mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE); }}private void dispatchStopIfNeeded(a) {
        if (mStartedCounter == 0 && mPauseSent) {
            mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
            mStopSent = true; }}void attach(Context context) {
        mHandler = new Handler();
        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
        Application app = (Application) context.getApplicationContext();
        / / before no Lifecycle components, using ActivityLifecycleCallbacks to monitor all of the Activity Lifecycle
        app.registerActivityLifecycleCallbacks(new EmptyActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                ReportFragment.get(activity).setProcessListener(mInitializationListener);
            }

            @Override
            public void onActivityPaused(Activity activity) {
                activityPaused();
            }

            @Override
            public void onActivityStopped(Activity activity) { activityStopped(); }}); }}Copy the code

Before no Lifecycle components, using ActivityLifecycleCallbacks registered in Application for all the Activity life cycle monitoring, Also use the ActivityLifecycleCallbacks here, but the true object into a single Activity, feels more flexible to use.

Note: There is a question above, how is ProcessLifecycleOwner initialized? The answer is in the next section.

The final lifecycle state is distributed in the handleLifecycleEvent method of LifecycleRegistry, which calls the sync method.

private void sync(a) {
    LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
    if (lifecycleOwner == null) {
        Log.w(LOG_TAG, "LifecycleOwner is garbage collected, you shouldn't try dispatch "
                + "new events from it.");
        return;
    }

    while(! isSynced()) { mNewEventOccurred =false;
        // no need to check eldest for nullability, because isSynced does it for us.
        if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
            backwardPass(lifecycleOwner);
        }
        Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
        if(! mNewEventOccurred && newest ! =null
                && mState.compareTo(newest.getValue().mState) > 0) {
            // Key method
            forwardPass(lifecycleOwner);
        }
    }
    mNewEventOccurred = false;
}
Copy the code

Continue to look at the forwardPass method, the source is as follows:

private void forwardPass(LifecycleOwner lifecycleOwner) {
    Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
            mObserverMap.iteratorWithAdditions();
    while(ascendingIterator.hasNext() && ! mNewEventOccurred) { Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next(); ObserverWithState observer = entry.getValue();while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
                && mObserverMap.contains(entry.getKey()))) {
            pushParentState(observer.mState);
            // Lifecycle state distributionobserver.dispatchEvent(lifecycleOwner, upEvent(observer.mState)); popParentState(); }}}Copy the code

Continue with the dispatchEvent method

static class ObserverWithState {
        State mState;
        GenericLifecycleObserver mLifecycleObserver;

        ObserverWithState(LifecycleObserver observer, State initialState) {
            GenericLifecycleObserver GenericLifecycleObserver GenericLifecycleObserver
            mLifecycleObserver = Lifecycling.getCallback(observer);
            mState = initialState;
        }

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

By convention, look at the GenericLifecycleObserver implementation class to see the flow of the lifecycle state distributed in the onStateChanged method, The GenericLifecycleObserver implementation class used depends on the observer passed in by the getCallback method.

 @NonNull
static GenericLifecycleObserver getCallback(Object object) {
    // Directly inherits DefaultLifecycleObserver
    if (object instanceof FullLifecycleObserver) {
        return new FullLifecycleObserverAdapter((FullLifecycleObserver) object);
    }
    // Conjecture: If the custom Observer inherits from GenericLifecycleObserver when managing the lifecycle
    if (object instanceof GenericLifecycleObserver) {
        return (GenericLifecycleObserver) object;
    }

    // Use an Annotation Processor.
    finalClass<? > klass = object.getClass();int type = getObserverConstructorType(klass);
    if (type == GENERATED_CALLBACK) {
        List<Constructor<? extends GeneratedAdapter>> constructors =
                sClassToAdapters.get(klass);
        if (constructors.size() == 1) {
            GeneratedAdapter generatedAdapter = createGeneratedAdapter(
                    constructors.get(0), object);
            return new SingleGeneratedAdapterObserver(generatedAdapter);
        }
        GeneratedAdapter[] adapters = new GeneratedAdapter[constructors.size()];
        for (int i = 0; i < constructors.size(); i++) {
            adapters[i] = createGeneratedAdapter(constructors.get(i), object);
        }
        return new CompositeGeneratedAdaptersObserver(adapters);
    }
    return new ReflectiveGenericLifecycleObserver(object);
}
Copy the code

If it is direct inheritance DefaultLifecycleObserver FullLifecycleObserverAdapter, generated in its implementation onStatChanged callback methods would eventually in the life cycle state in the distributed, Would be returned to their original create LifecycleListener1, so listen to Activity in the LifecycleListener1 life cycle state, see FullLifecycleObserverAdapter source code is as follows:

class FullLifecycleObserverAdapter implements GenericLifecycleObserver {

    private final FullLifecycleObserver mObserver;

    FullLifecycleObserverAdapter(FullLifecycleObserver observer) {
        mObserver = observer;
    }

    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        // Callback to the corresponding lifecycle method based on the specific Event
        switch (event) {
            case ON_CREATE:
                mObserver.onCreate(source);
                break;
            case ON_START:
                mObserver.onStart(source);
                break;
            case ON_RESUME:
                mObserver.onResume(source);
                break;
            case ON_PAUSE:
                mObserver.onPause(source);
                break;
            case ON_STOP:
                mObserver.onStop(source);
                break;
            case ON_DESTROY:
                mObserver.onDestroy(source);
                break;
            case ON_ANY:
                throw new IllegalArgumentException("ON_ANY must not been send by anybody"); }}}Copy the code

Initialization of ProcessLifecycleOwner

We know the Activity in the life cycle state monitoring and use the ActivityLifecycleCallbacks ActivityLifecycleCallbacks registration is registered in the Application, it is how to sign up, Its registration is done in the initialization of ProcessLifecycleOwner, Find ProcessLifecycleOwner init method call is invoked in ProcessLifecycleOwnerInitializer onCreate method, the source code is as follows:

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

    // ...
}
Copy the code

ProcessLifecycleOwnerInitializer is obviously a ContentProvider, its onCreate method in addition to initialize ProcessLifecycleOwner, LifecycleDispatcher init LifecycleDispatcher init LifecycleDispatcher

class LifecycleDispatcher {

    private static AtomicBoolean sInitialized = new AtomicBoolean(false);
    // LifecycleDispatcher initialization
    static void init(Context context) {
        if (sInitialized.getAndSet(true)) {
            return;
        }
        / / register ActivityLifecycleCallbacks
        ((Application) context.getApplicationContext())
                .registerActivityLifecycleCallbacks(new DispatcherActivityCallback());
    }

    @SuppressWarnings("WeakerAccess")
    @VisibleForTesting
    static class DispatcherActivityCallback extends EmptyActivityLifecycleCallbacks {

        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            // Add an unbounded Fragment to the Activity
            ReportFragment.injectIfNeededIn(activity);
        }

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

Before analysis, here the registered ActivityLifecycleCallbacks effect on ActivityLifecycleCallbacks and registered are not the same, To add a ReportFragment to an Activity, add a ReportFragment to the Activity. To add a ReportFragment to an Activity, add ReportFragment to the Activity. The injectIfNeededIn method will only be added a second time if ReportFragment has not been added.

Front know ProcessLifecycleOwnerInitializer is a ContentProvider, when ContentProvider create will start with the creation of the corresponding process, You can start the ContentProvider process by using the Main method of ActivityThread. AndroidXRef is a tool for viewing the Android source code.