This is the sixth day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

Lifecycle will be used often enough that you will be familiar with how Lifecycle is used so I will omit this section today.

Think of a question. What pain point does it solve?

In a real application, there would end up being too many calls to administrative interfaces and other components in response to the current state of the lifecycle. Managing multiple components puts a lot of code in lifecycle methods such as onStart() and onStop(), which makes them difficult to maintain. There is also no guarantee that a component will not start after an Activity/Fragment has stopped.

So how Lifecycle solves these problems, let’s get right into analyzing the source code.

Lifecycle class

Before analyzing Lifecycle, what does Lifecycle do internally?

public abstract class Lifecycle {
    // Add LifecycleObserver to be notified when LifecycleOwner changes state.
    @MainThread
    public abstract void addObserver(@NonNull LifecycleObserver observer);
    // Remove the given observer from the observer list.
    @MainThread
    public abstract void removeObserver(@NonNull LifecycleObserver observer);
    // Returns the current state of the life cycle
    public abstract State getCurrentState(a);

// Lifecycle events, corresponding to Activity lifecycle methods
    public enum Event {
        ON_CREATE,
        ON_START,
        ON_RESUME,
        ON_PAUSE,
        ON_STOP,
        ON_DESTROY,
      // Can respond to any event
        ON_ANY  
    }
    
    // Life cycle state (Event is the Event that enters this state)
    public enum State {
        DESTROYED,
        INITIALIZED,
        CREATED,
        STARTED,
        RESUMED;

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

You can see that two enumerations are provided to associate the component’s lifecycle state:

  • Event: life cycle event, corresponding to Activity/Fragment life cycle methods.
  • State: lifecycle states, and events are the events that you enter into a state.

All right, so now we’re going to do the analysis in earnest.

How do you do lifecycle distribution

public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        LifecycleOwner.ViewModelStoreOwner.SavedStateRegistryOwner.OnBackPressedDispatcherOwner {...private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this); .@NonNull
    @Override
    public Lifecycle getLifecycle(a) {
        return mLifecycleRegistry;
    }
          
              @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mSavedStateRegistryController.performRestore(savedInstanceState);
      / / note
        ReportFragment.injectIfNeededIn(this);
        if(mContentLayoutId ! =0) { setContentView(mContentLayoutId); }}... }Copy the code

In Android Support Library 26.1.0 and later, LifecycleOwner interfaces are implemented by default for activities and fragments, and LifecycleOwner can be understood as being observed. You can see here that getLifeCycle() gets LifecycleRegistry, where LifecycleRegistry is an implementation of LifeCyle. We created the ReportFragment in onCreate() as a lifecycle observation, and it suddenly became clear that it was the ReportFragment that was helping us distribute events.

public class ReportFragment extends Fragment {
  
  public static void injectIfNeededIn(Activity activity) {
        if (Build.VERSION.SDK_INT >= 29) {
          // In API 29 and above, callbacks can be registered directly to retrieve the lifecycle
            activity.registerActivityLifecycleCallbacks(
                    new LifecycleCallbacks());
        }
        android.app.FragmentManager manager = activity.getFragmentManager();
     	// Before API29, use fragment to get the life cycle
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(newReportFragment(), REPORT_FRAGMENT_TAG).commit(); manager.executePendingTransactions(); }}...@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);
        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 instanceof LifecycleRegistry) {
              // Handle events using the handleLifecycleEvent method of LifecycleRegistry((LifecycleRegistry) lifecycle).handleLifecycleEvent(event); }}}}Copy the code

InjectIfNeededIn adds a ReportFragment to the activity and has no layout.

Notice that the fragment’s role here is to distribute the lifecycle, with the dispatch() method inside, and what’s really implemented inside is the handleLifecycleEvent method for LifecycleRegistry to handle events.

LifecycleRegistry event distribution

### LifecycleRegistry

private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
  
  public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
  // According to the corresponding state of the Event lifecycle method
        State next = getStateAfter(event);
  			// Move to the following state
        moveToState(next);
    }

 private void moveToState(State next) {
   // If the status is inconsistent, it is not processed
        if (mState == next) {
            return;
        }
   // Set the new state
       mState = next;
        if(mHandlingEvent || mAddingObserverCounter ! =0) {
            mNewEventOccurred = true;
            // we will figure out what to do on upper level.
            return;
        }
        mHandlingEvent = true;
   // Synchronize lifecycle distribution
       sync();
        mHandlingEvent = false;
    }

 private void sync(a) { LifecycleOwner lifecycleOwner = mLifecycleOwner.get(); .// All observers are synchronized
        while(! isSynced()) { mNewEventOccurred =false;
            // mObserverMap stores observers
            if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
              Observer. dispatchEvent(lifecycleOwner, event); Distribute, which is to call the method in Object server with State
              //mState is smaller than the oldest observer state
              backwardPass(lifecycleOwner);
            }
            Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
            if(! mNewEventOccurred && newest ! =null
                    && mState.compareTo(newest.getValue().mState) > 0) {
              //mState is larger than the state of the latest observer
                forwardPass(lifecycleOwner);
            }
        }
        mNewEventOccurred = false;
    }

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);
    }
Copy the code

To process distribution, first obtain the corresponding state of the event, then call movetoState to moveto the new state, do nothing if the current state is the same as the state to be in, and finally synchronize the life cycle state to all observers.

In the sync method, the current state is compared with the newest and younger states in the mObserverMap to determine whether the current state is forward or backward. BackwardPass and forwardPass are basically the same, so take forwardPass for example.

# # #LifecycleRegistry

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);
              Observer. dispatchEvent is called for event handlingobserver.dispatchEvent(lifecycleOwner, upEvent(observer.mState)); popParentState(); }}}Copy the code

Call observer.dispatchEvent ();

All the observers are storedmObserverMapLet’s see how it’s stored.

Back to the LifecycleRegistry code, when we call getLifecycle().addobServer (myLocationListener) internally:

public class LifecycleRegistry extends Lifecycle {
  private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
              newFastSafeIterableMap<>(); .@Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
    // will be wrapped as the corresponding Observer
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
    // Put the observer into the map for subsequent distribution
        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++;
    // Through the while loop, the state of the new observer is continuously synchronized to the latest state, mState.
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
          // Go further
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();
            targetState = calculateTargetState(observer);
        }

        if (!isReentrance) {
            sync();
        }
        mAddingObserverCounter--;
    }
  
}
Copy the code

Add the observer to the mObserverMap, and then loop to find the latest observer and synchronize the status to the past. The previous events can be distributed one by one, which is sticky.

Let’s move onObserverWithStateHow to get the annotated method to execute?

Along the statefulObserve. DispatchEvent () method to continue to look down.

### LifecycleRegister/ObserverWithState
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);
          // Prevent duplication
            mState = min(mState, newState);
          // The event notifies the observermLifecycleObserver.onStateChanged(owner, event); mState = newState; }}Copy the code

ObserverWithState is an internal class of LifecycleRegister, where mState is used to reassign when a new event occurs, preventing repeated notifications.

In Lifecycling. LifecycleEventObserver (observer) method returns the lifecycleEventObserver object.

public interface LifecycleEventObserver extends LifecycleObserver {
    // Called when a state transition event occurs
    void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event);
}
Copy the code

Take a look at what Lifechcling does:

//Lifecycling.java
    @NonNull
    static LifecycleEventObserver lifecycleEventObserver(Object object) {
        boolean isLifecycleEventObserver = object instanceof LifecycleEventObserver;
        boolean isFullLifecycleObserver = object instanceof FullLifecycleObserver;
        if (isLifecycleEventObserver && isFullLifecycleObserver) {
            return new FullLifecycleObserverAdapter((FullLifecycleObserver) object,
                    (LifecycleEventObserver) object);
        }
        if (isFullLifecycleObserver) {
            return new FullLifecycleObserverAdapter((FullLifecycleObserver) object, null);
        }

        if (isLifecycleEventObserver) {
            return (LifecycleEventObserver) object;
        }

        finalClass<? > klass = object.getClass();// This method uses klass to get annotations for recording
        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);
    }

/ / getObserverConstructorType (klass), and finally the method called
boolean hasLifecycleMethods = ClassesInfoCache.sInstance.hasLifecycleMethods(klass);
Copy the code

After return to ObserverWithState, access to the observer status change invokes mLifecycleObserver. OnStateChanged (the owner, the event); There are three FullLifecycleObserverAdapter, CompositeGeneratedAdaptersObserver, ReflectiveGenericLifecycleObserver. And we focus on ComponentActivity, so LifecycleEventObserver ReflectiveGenericLifecycleObserver implementation class is.

The LifecycleObserver method is executed

### ReflectiveGenericLifecycleObserver
class ReflectiveGenericLifecycleObserver implements LifecycleEventObserver {
    private final Object mWrapped;
    private final CallbackInfo mInfo;

    ReflectiveGenericLifecycleObserver(Object wrapped) {
        mWrapped = wrapped;
        mInfo = ClassesInfoCache.sInstance.getInfo(mWrapped.getClass());
    }

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

Here you see invokeCallbacks calling CallbackInfo for distribution. CallbackInfo: ClassesInfoCache: ClassesInfoCache: ClassesInfoCache: ClassesInfoCache: ClassesInfoCache: ClassesInfoCache: ClassesInfoCache: ClassesInfoCache

# # #ClassInfoCache
  
CallbackInfo getInfo(Class
        klass) {
        CallbackInfo existing = mCallbackMap.get(klass);
        if(existing ! =null) {
            return existing;
        }
        existing = createInfo(klass, null);
        return existing;
    }

private CallbackInfo createInfo(Class<? > klass,@Nullable Method[] declaredMethods) { 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); } } Class<? >[] interfaces = klass.getInterfaces();// Iterate through each method to get an annotation on the method called OnLifecycleEvent, which is used to implement the LifecycleObserver interface
        for(Class<? > intrfc : interfaces) {for(Map.Entry<MethodReference, Lifecycle.Event> entry : getInfo( intrfc).mHandlerToEvent.entrySet()) { verifyAndPutHandler(handlerToEvent, entry.getKey(), entry.getValue(), klass); } } Method[] methods = declaredMethods ! =null ? declaredMethods : getDeclaredMethods(klass);
        boolean hasLifecycleMethods = false;
        for (Method method : methods) {
            OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class);
            if (annotation == null) {
                continue;
            }
            hasLifecycleMethods = true; Class<? >[] 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");
            }
          // Create a MethodReference containing the method that uses the annotation
          // This method is the last method to call invoke
            MethodReference methodReference = new MethodReference(callType, method);
          // Store MethodReference and its Event in a handlerToEvent whose type is Map
      ,>
            verifyAndPutHandler(handlerToEvent, methodReference, event, klass);
        }
  			// And pass handlerToEvent in
        CallbackInfo info = new CallbackInfo(handlerToEvent);
        mCallbackMap.put(klass, info);
        mHasLifecycleMethods.put(klass, hasLifecycleMethods);
        return info;
    }
Copy the code

With that in mind, let’s go back to the invokeCallbacks method:

### ClassesInfoCache/CallbackInfo
  
   static class CallbackInfo {
        final Map<Lifecycle.Event, List<MethodReference>> mEventToHandlers;
        final Map<MethodReference, Lifecycle.Event> mHandlerToEvent;

        CallbackInfo(Map<MethodReference, Lifecycle.Event> handlerToEvent) {
            mHandlerToEvent = handlerToEvent;
            mEventToHandlers = new HashMap<>();
          // The meaning of the loop is to convert a handlerToEvent to a HashMap with a key value of event and a value of MethodReference.
            for (Map.Entry<MethodReference, Lifecycle.Event> entry : handlerToEvent.entrySet()) {
                Lifecycle.Event event = entry.getValue();
                List<MethodReference> methodReferences = mEventToHandlers.get(event);
                if (methodReferences == null) {
                    methodReferences = newArrayList<>(); mEventToHandlers.put(event, methodReferences); } methodReferences.add(entry.getKey()); }}@SuppressWarnings("ConstantConditions")
        void invokeCallbacks(LifecycleOwner source, Lifecycle.Event event, Object target) {
          // We pass in meventtohandlers.get (event), which is the collection of MethodReference for the event.
            invokeMethodsForEvent(mEventToHandlers.get(event), source, event, target);
            invokeMethodsForEvent(mEventToHandlers.get(Lifecycle.Event.ON_ANY), source, event,
                    target);
        }

        private static void invokeMethodsForEvent(List
       
         handlers, LifecycleOwner source, Lifecycle.Event event, Object mWrapped)
        {
            if(handlers ! =null) {
              // The MethodReference collection is traversed and the invokeCallback method is called.
                for (int i = handlers.size() - 1; i >= 0; i--) { handlers.get(i).invokeCallback(source, event, mWrapped); }}}}Copy the code

The event is executed, the collection of MethodReference is traversed, and the invokeCallback method of MethodReference is called.

    static final class MethodReference {
        final int mCallType;
        final Method mMethod;

        MethodReference(int callType, Method method) {
            mCallType = callType;
            mMethod = method;
            mMethod.setAccessible(true);
        }

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

On MethodReference, invoke is used to reflect the method based on the callType.

Finally, a picture to summarize what we saw today:

Lifecycle Lifecycle will begin with Android Jetpack Lifecycle will begin with Lifecycle

reference

Lifecycle official documentation

Lifecycle will help Lifecycle Lifecycle Lifecycle

Jetpack AAC complete analysis (a) Lifecycle complete mastery!

Android Jetpack– Lifecycle full parsing