Enjoy learning jetpack - the core principle of lifecycle: lifecycle registry

Posted by philipreed on Sun, 20 Feb 2022 17:08:05 +0100

Core class:

Lifecycle can effectively avoid memory leakage and solve common problems in android life cycle. It is an object representing android life cycle and status;

Lifecycle is an abstract class that implements the subclass LifecycleRegistry

public class LifecycleRegistry extends Lifecycle{
  ......
}

Application of lifecycle registry in Android:

-LifecycleOwner is used to connect objects with lifecycles;

public interface LifecycleOwner {
    /**
     * Returns the Lifecycle of the provider.
     */
    @NonNull
    Lifecycle getLifecycle();
}

In the new version SDK In the bag, Activity/Fragment It has been implemented by default LifecycleOwner Interface;
Looking at the source code, we can see that, Activity/Fragment The implementation of is return LifecycleRegistry Object:
public Lifecycle getLifecycle() {
   return mLifecycleRegistry;
}

in the light of Service,Android Provided separately LifeCycleService,Not like Activity,Fragment By default LifeCycleOwner. 

in the light of Application,Android Provided ProcessLifeCycleOwner - Monitor the entire application lifecycle.

-LifecycleObserver is used to observe and check the LifecycleOwner;

- Activity  or  Fragment

getLifecycle().addObserver(Realized LifecycleObserver Observer of interface);

- Observer

public class LifeCycleObserverTest implements LifecycleObserver {

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    public void onCreateOb(){

    }

}

Basic principle:

#1 the parent classes ComponentActivity and Fragment of the Activity we use everyday implement the Lifecycle owner interface, and the Lifecycle objects returned by the getLifecycle() method are LifecycleRegistry

#2. AppCompatActivity attaches a ReportFragment without UI interface by default. The ReportFragment will obtain the event change notification of AppCompatActivity in different ways according to the system version number of the user's mobile phone, and finally call the handlellifecycle event (Lifecycle.Event) method of LifecycleRegistry to update the lifecycle The event is passed out. At this point, LifecycleRegistry gets the lifecycle Event

#3  androidx.fragment.app.Fragment will directly call the handlellifecycle event (Lifecycle.Event) method of LifecycleRegistry internally to complete the event notification. At this time, LifecycleRegistry also gets the lifecycle Event

#4. Lifecycleregistry will package the LifecycleObserver objects passed in from the external addObserver into the LifecycleEventObserver objects inside the ObserverWithState class, shielding the differences of the lifecycleobservers passed in from the outside (which may be interfaces or annotations)

#5 lifecycleregistry completes the final event callback by directly calling the onStateChanged method of the LifecycleEventObserver object inside the ObserverWithState class. So far, the whole process is completed

Core principle analysis - how to perceive the life cycle? How do I distribute lifecycle states to observers?

1) How to perceive the life cycle?

Let's take ComponentActivity as an example.

- ComponentActivity

public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        LifecycleOwner,
        ViewModelStoreOwner,
        SavedStateRegistryOwner,
        OnBackPressedDispatcherOwner {

    private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

    // Lazily recreated from NonConfigurationInstances by getViewModelStore()
    private ViewModelStore mViewModelStore;

    ......

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mSavedStateRegistryController.performRestore(savedInstanceState);
        // #1 core code
        ReportFragment.injectIfNeededIn(this);
        if (mContentLayoutId != 0) {
            setContentView(mContentLayoutId);
        }
    }

    ......

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }

    ......

}

In the onCreate method of ComponentActivity, a transparent Fragment without UI will be added through the FragmentManager for the perception of life cycle. The implementation principle is the same as Glide.

- ReportFragment

- 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();
        }
    }

    ......    

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

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

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

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

    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 instanceof LifecycleRegistry) {
                ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
            }
        }
    }

    ......

}

When the life cycle changes, ReportFragment finally calls the handlelife cycleevent method of the LifecycleRegistry object of the corresponding Activity through the dispatch method to complete the distribution of life cycle events.

2) How do I distribute lifecycle states to observers?

- LifecycleRegistry

In lifecycle registry, call the chain through the following methods:

Handlellifecycle event - > movetostate - > sync - > traverse mObserverMap(key: lifecycle observer, value: reflective genericlifecycle observer) - > mllifecycle observer onStateChanged

Specific analysis:
In Jetpack, there are five states in the life cycle of the page. The life cycle changes in different scenarios will flow in these five states, and moveToState and sync do this.

- LifecycleRegistry

    public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        State next = getStateAfter(event);// Get the corresponding status value according to the current life cycle event
        moveToState(next);
    }

moveToState The core of is the global variable mState Saved the current State,And called sync method:

 private void sync() {
        // The lifecycle owner here is our Activity or Fragment
        // This weak reference is generated in the construction method of LifecycleRegistry, that is, LifecycleRegistry holds the weak reference of Activity or Fragment
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        
        // The lifecycle State flows forward or backward
        while (!isSynced()) {
            mNewEventOccurred = false;
            // no need to check eldest for nullability, because isSynced does it for us.
            if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
                backwardPass(lifecycleOwner);
            }
            Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
            if (!mNewEventOccurred && newest != null
                    && mState.compareTo(newest.getValue().mState) > 0) {
                forwardPass(lifecycleOwner);
            }
        }
        mNewEventOccurred = false;
    }

Here comes a new concept - State

Flow to the corresponding status through the value of life cycle events:

- LifecycleRegistry
  
  static State getStateAfter(Event event) {
        switch (event) {
            case ON_CREATE:
            case ON_STOP:
                return CREATED;
            case ON_START:
            case ON_PAUSE:
                return STARTED;
            case ON_RESUME:
                return RESUMED;
            case ON_DESTROY:
                return DESTROYED;
            case ON_ANY:
                break;
        }
        throw new IllegalArgumentException("Unexpected event value " + event);
    }

Then we analyze the core methods of life cycle state: forwardPass and backwardPass. The functions of these two methods are the same, but one is forward flow and the other is backward flow, which can be viewed according to the above figure. Take forwardPass as an example:

- LifecycleRegistry

private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
            new FastSafeIterableMap<>();

    private void forwardPass(LifecycleOwner lifecycleOwner) {
        // Mbobservermap is the Map collection of all observers, key: lifecycleobserver, value: reflective genericlifecycleobserver (similar to EventBus, all registered methods of observers are obtained through reflection [registered through @ onllifecycle event annotation])
        Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
                mObserverMap.iteratorWithAdditions();
        while (ascendingIterator.hasNext() && !mNewEventOccurred) {
            Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();
            // Get the corresponding observer
            ObserverWithState observer = entry.getValue();
            while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
                    && mObserverMap.contains(entry.getKey()))) {
                pushParentState(observer.mState);// Save the status before distribution so that the distributed problems can be rolled back
                // Call the watcher's dispatchEvent - the final reflection calls the registered lifecycle methods
                observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
                popParentState();// Remove pre distribution status
            }
        }
    }

If you understand the principle of EventBus, you don't have to look at it below.

Here, we analyze how the lifecycle state flows after the lifecycle occurs and distribute it to the corresponding observer.

Let's continue to analyze the observer of forwardPass How dispatchEvent is distributed.

Looking at the source code, we will find that this Observer is not the original lifecycle Observer, but a layer of Observer withstate based on the original lifecycle Observer. The reason for packaging one layer is to encapsulate the Observer and the registration method.

    static class ObserverWithState {
        State mState;
        LifecycleEventObserver mLifecycleObserver;

        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);
            mLifecycleObserver.onStateChanged(owner, event);
            mState = newState;
        }
    }

Here are the core codes:

Lifecycling.lifecycleEventObserver(observer)

That is, while registering the observer, the relationship encapsulation of observer registration method = 1:1 is completed through this method call.

- Lifecycling

    @NonNull
    static LifecycleEventObserver lifecycleEventObserver(Object object) {
        ......
        return new ReflectiveGenericLifecycleObserver(object);
    }

After various flows, the reflective genericlifecycleobserver object must eventually be returned.

- ReflectiveGenericLifecycleObserver 

class ReflectiveGenericLifecycleObserver implements LifecycleEventObserver {
    private final Object mWrapped;
    private final CallbackInfo mInfo;
    
    // The Object here is our observer
    ReflectiveGenericLifecycleObserver(Object wrapped) {
        mWrapped = wrapped;
        mInfo = ClassesInfoCache.sInstance.getInfo(mWrapped.getClass());
    }

    // Reflection triggered call
    @Override
    public void onStateChanged(LifecycleOwner source, Event event) {
        mInfo.invokeCallbacks(source, event, mWrapped);
    }
}

Similarly, the collection of ClassInfo is completed in the constructor [you can see that this method is used many times]

- ReflectiveGenericLifecycleObserver Core method

ClassesInfoCache.sInstance.getInfo(mWrapped.getClass());

How to collect what methods observers have registered? The core is reflection + annotation + Map.

- ClassInfoCache

Map: 

private final Map<Class, CallbackInfo> mCallbackMap = new HashMap<>();

reflex + Notes:

getInfo Will trigger createInfo Call of, createInfo Core code of:

        ......
        Method[] methods = declaredMethods != null ? declaredMethods : getDeclaredMethods(klass);// klass is our observer
        ......
        for (Method method : methods) {
            OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class);
            ......
            Lifecycle.Event event = annotation.value();
            ......
            MethodReference methodReference = new MethodReference(callType, method);
            // Map<MethodReference, Lifecycle.Event> handlerToEvent = new HashMap<>();
            verifyAndPutHandler(handlerToEvent, methodReference, event, klass);
        }
        CallbackInfo info = new CallbackInfo(handlerToEvent);
        mCallbackMap.put(klass, info);


Returning to ObserverWithState, when the flow occurs in the life cycle, that is, the call of forwardPass, will trigger the call of dispatchEvent of ObserverWithState, and finally trigger the call of onStateChanged method of reflective genericlifecycle Observer:

- ReflectiveGenericLifecycleObserver

    @Override
    public void onStateChanged(LifecycleOwner source, Event event) {
        mInfo.invokeCallbacks(source, event, mWrapped);
    }

That is, the invokeCallbacks method of CallbackInfo is called. Finally, the registration method is called through reflection.

- MethodReference

        void invokeCallback(LifecycleOwner source, Lifecycle.Event event, Object target) {
            //noinspection TryWithIdenticalCatches
            try {
                switch (mCallType) {
                    case CALL_TYPE_NO_ARG:
                        mMethod.invoke(target);
                        break;
                    case CALL_TYPE_PROVIDER:
                        mMethod.invoke(target, source);
                        break;
                    case CALL_TYPE_PROVIDER_WITH_EVENT:
                        mMethod.invoke(target, source, event);
                        break;
                }
            } catch (InvocationTargetException e) {
                throw new RuntimeException("Failed to call observer method", e.getCause());
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }

Topics: Android