An overview of the

Last time we talked about Android touch event delivery, this time we’ll talk about Jetpack. Specifically, I’m going to talk about LifeCycle, because the official library JetPack is quite large. I won’t go into Jetpack’s past or present life, or what he does. Here we will focus on the basic use of LifeCycle and improving on the MVP example we talked about last time with LifeCycle.

Then look at how LifeCycle helps activities or fragments manage their LifeCycle from a source perspective. Articles analyzing other components of Jetpack will follow.

We know that when we load data with certain modules, we often need to listen for the Activity or Fragment life cycle. Adjust the data loading or callback strategy as the life cycle changes.

Instead of using component management, you can call the module’s lifecycle method manually in the Activity or Fragment lifecycle callback method. This can lead to a lot of such rigid code in the page lifecycle callback method, which is also difficult to manage. LifeCycle is used to solve some of these problems.

1, use,

With LifeCycle there is no need to add dependencies as they are already built in. You need to add dependencies if you want to use Viewmodel and Livedata, which will be analyzed later.

First of all, since it’s lifecycle listening, there will be observers and observed. The interface the observer needs to implement is the LifecycleOwner, which is an Activity or Fragment owner. Both implement the LifecycleOwner interface, and we can look at the Activity’s parent ComponentActivity:

public class ComponentActivity extends androidx.core.app.ComponentActivity implements LifecycleOwner, ... . {Copy the code

The interface that the LifecycleObserver needs to implement is the LifecycleObserver. Let’s add a LifeCycle listening method to a Presenter using the MVP architecture example.

Let BasePresenter implement the observer interface first:

LifecycleObserver public class BasePresenter<V extends IView> implements LifecycleObserver {private V mView; public void attach(V iView) { this.mView = iView; } public void detach() { this.mView = null; } public V getView() { return mView; }}Copy the code

We then add a few lifecycle methods to the BasePresenter implementation class Presenter, annotating it with ** @onlifecycleEvent ** :

//  Presenter.java

    // onCreate
    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    public void onCreate(){
        Log.d(TAG, "-----------LifecycleObserver -- onCreate");
    }
    // onStart
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    public void onStart(){
        Log.d(TAG, "-----------LifecycleObserver -- onStart");
    }
    // onPause
    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void onPause(){
        Log.d(TAG, "-----------LifecycleObserver -- onPause");
    }
    // onStop
    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    public void onStop(){
        Log.d(TAG, "-----------LifecycleObserver -- onStop");
    }
    // onDestroy
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    public void onDestroy(){
        Log.d(TAG, "-----------LifecycleObserver -- onDestroy");
    }
Copy the code

Then add an observer when BaseMvpActivity is initialized:

// BaseMvpActivity.java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(); initView(); initData(); mPresenter = createP(); //mPresenter.attach(this); // comment 1, addObserver getLifecycle().addobserver (mPresenter); } @Override protected void onDestroy() { super.onDestroy(); // mPresenter.detach(); // Remove the observer getLifecycle().removeObserver(mPresenter); }Copy the code

The last example used the template design pattern, so now the addition and removal of lifecycle observers are in the template as well. Then start the Activity and exit, and see the print result:

com.ethan.mvpapplication D/Presenter: -----------LifecycleObserver -- onCreate
com.ethan.mvpapplication D/Presenter: -----------LifecycleObserver -- onStart
com.ethan.mvpapplication D/Presenter: -----------LifecycleObserver -- onPause
com.ethan.mvpapplication D/Presenter: -----------LifecycleObserver -- onStop
com.ethan.mvpapplication D/Presenter: -----------LifecycleObserver -- onDestroy
Copy the code

The MVP of the Demo:

2. Source code analysis

Lifecycle Lifecycle listening will be examined. As simple as that, go straight into the getLifecycle() method in comment 1 above and see what happens:

//  ComponentActivity.java

private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
Copy the code

What is returned is a LifecycleRegistry object that we can click on to see. LifecycleRegistry is an implementation class of the abstract class Lifecycle:

public abstract class Lifecycle { @MainThread public abstract void addObserver(@NonNull LifecycleObserver observer); @MainThread public abstract void removeObserver(@NonNull LifecycleObserver observer); @MainThread @NonNull public abstract androidx.lifecycle.Lifecycle.State getCurrentState(); public enum Event { ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY, ON_ANY } public enum State { DESTROYED, INITIALIZED, CREATED, STARTED, RESUMED; public boolean isAtLeast(@NonNull androidx.lifecycle.Lifecycle.State state) { return compareTo(state) >= 0; }}}Copy the code

Lifecycle contains not only methods to add and remove observers, but also enumerations of Event and State. As you can see, the Event enumeration contains several of the Activity’s most important lifecycle methods.

LifeCycle will listen to LifeCycle: LifeCycle

public class ComponentActivity extends androidx.core.app.ComponentActivity implements LifecycleOwner, ...... { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); . / / comment 2, ComponentActivity injection ReportFragment ReportFragment. InjectIfNeededIn (this); . }... @Override public androidx.lifecycle.Lifecycle getLifecycle() { return mLifecycleRegistry; }}Copy the code

It would be possible to call the observer’s corresponding method in each of the life cycle callbacks for ComponentActivity, but you can see that this is not done in the ComponentActivity class. Instead, inject the current Activity object into the ReportFragment at comment 2 above. Let’s see what the ReportFragment does:

public class ReportFragment extends Fragment { private static final String REPORT_FRAGMENT_TAG = "androidx.lifecycle" + ".LifecycleDispatcher.report_fragment_tag"; public static void injectIfNeededIn(Activity activity) { android.app.FragmentManager manager = activity.getFragmentManager(); If (manager. FindFragmentByTag (REPORT_FRAGMENT_TAG) = = null) {/ / comment 3, create ReportFragment added to the Activity, Make life cycle and the synchronization of the manager. The beginTransaction (). The add (new androidx. Lifecycle. ReportFragment (), REPORT_FRAGMENT_TAG), commit (); manager.executePendingTransactions(); } } static androidx.lifecycle.ReportFragment get(Activity activity) { return (androidx.lifecycle.ReportFragment) activity.getFragmentManager().findFragmentByTag( REPORT_FRAGMENT_TAG); } / / distribute lifecycle callback event private void dispatchCreate (androidx. Lifecycle. ReportFragment. ActivityInitializationListener listener) {  if (listener ! = null) { listener.onCreate(); }}... . @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); dispatchCreate(mProcessListener); dispatch(androidx.lifecycle.Lifecycle.Event.ON_CREATE); } @Override public void onStart() { super.onStart(); // Comment 4, start calling the observer's lifecycle dispatchStart(mProcessListener); dispatch(androidx.lifecycle.Lifecycle.Event.ON_START); }... . private void dispatch(androidx.lifecycle.Lifecycle.Event event) { Activity activity = getActivity(); if (activity instanceof LifecycleRegistryOwner) { ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event); return; } if (activity instanceof LifecycleOwner) { androidx.lifecycle.Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle(); Lifecycle instanceof LifecycleRegistry if (lifecycle instanceof LifecycleRegistry) { LifecycleRegistry) lifecycle. HandleLifecycleEvent (Event); }}}}Copy the code

As you can see in comment 3 above, a Fragment is created and then added to the Activity. This way, the newly created Fragment and Activity can synchronize their life cycles. Later, in comment 4 above, LifecycleObserver related lifecycle methods can be called in the Fragment’s various lifecycle methods.

That is, ComponentActivity creates a ReportFragment and gives the transaction for the lifecycle callback to the Fragment. Is this SAO operation familiar? That’s right! Glide manages the life cycle the same way we analyzed it earlier.

In comment 5 above, let’s look again at the lifecycle event distribution and see where the observer method ends up being called:

// LifecycleRegistry.java static class ObserverWithState { androidx.lifecycle.Lifecycle.State mState; LifecycleEventObserver mLifecycleObserver; ObserverWithState(LifecycleObserver observer, Androidx. Lifecycle. Lifecycle. State initialState) {/ / get ReflectiveGenericLifecycleObserver mLifecycleObserver = object Lifecycling.lifecycleEventObserver(observer); mState = initialState; } void dispatchEvent(LifecycleOwner owner, androidx.lifecycle.Lifecycle.Event event) { ...... / / lifecycle callback event distribution mLifecycleObserver onStateChanged (the owner, the event); } } // Lifecycling.java static LifecycleEventObserver lifecycleEventObserver(Object object) { ..... / / returns the ReflectiveGenericLifecycleObserver return new androidx. Lifecycle. ReflectiveGenericLifecycleObserver (object); } // ReflectiveGenericLifecycleObserver.java class ReflectiveGenericLifecycleObserver implements LifecycleEventObserver { private final Object mWrapped; private final ClassesInfoCache.CallbackInfo mInfo; ReflectiveGenericLifecycleObserver(Object wrapped) { mWrapped = wrapped; mInfo = ClassesInfoCache.sInstance.getInfo(mWrapped.getClass()); } @Override public void onStateChanged(LifecycleOwner source, Androidx. Lifecycle. Lifecycle. The Event Event) {/ / lifecycle callback mInfo. InvokeCallbacks (source, Event, mWrapped); } } // ClassesInfoCache.java private ClassesInfoCache.CallbackInfo createInfo(Class klass, @Nullable Method[] declaredMethods) { Class superclass = klass.getSuperclass(); for (Method method : (methods) {// Reflect the various methods traversing the observer, save the annotated @onlifecycleEvent method in // Map object, OnLifecycleEvent annotation = method.getannotation (onlifecycleEvent.class); if (annotation == null) { continue; } Class<? >[] params = method.getParameterTypes(); . androidx.lifecycle.Lifecycle.Event event = annotation.value(); . ClassesInfoCache.MethodReference methodReference = new ClassesInfoCache.MethodReference(callType, method); verifyAndPutHandler(handlerToEvent, methodReference, event, klass); mCallbackMap.put(klass, info); mHasLifecycleMethods.put(klass, hasLifecycleMethods); }... return info; } static class CallbackInfo { final Map<androidx.lifecycle.Lifecycle.Event, List<ClassesInfoCache.MethodReference>> mEventToHandlers; final Map<ClassesInfoCache.MethodReference, androidx.lifecycle.Lifecycle.Event> mHandlerToEvent; CallbackInfo(Map<ClassesInfoCache.MethodReference, androidx.lifecycle.Lifecycle.Event> handlerToEvent) { mHandlerToEvent = handlerToEvent; mEventToHandlers = new HashMap<>(); for (Map.Entry<ClassesInfoCache.MethodReference, androidx.lifecycle.Lifecycle.Event> entry : handlerToEvent.entrySet()) { androidx.lifecycle.Lifecycle.Event event = entry.getValue(); List<ClassesInfoCache.MethodReference> methodReferences = mEventToHandlers.get(event); if (methodReferences == null) { methodReferences = new ArrayList<>(); mEventToHandlers.put(event, methodReferences); } methodReferences.add(entry.getKey()); } } @SuppressWarnings("ConstantConditions") void invokeCallbacks(LifecycleOwner source, androidx.lifecycle.Lifecycle.Event event, Object target) { invokeMethodsForEvent(mEventToHandlers.get(event), source, event, target); invokeMethodsForEvent(mEventToHandlers.get(androidx.lifecycle.Lifecycle.Event.ON_ANY), source, event, target); } private static void invokeMethodsForEvent(List<ClassesInfoCache.MethodReference> handlers, LifecycleOwner source, androidx.lifecycle.Lifecycle.Event event, Object mWrapped) { if (handlers ! = null) { for (int i = handlers.size() - 1; i >= 0; Handlers. Get (I). InvokeCallback (source, event, mWrapped); } } } } // ClassesInfoCache.MethodReference static class MethodReference { final int mCallType; final Method mMethod; . void invokeCallback(LifecycleOwner source, androidx.lifecycle.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); }}}Copy the code

Instead of drawing the sequence diagram, write the call flow roughly:

LifecycleRegistry.java

  • –> handleLifecycleEvent();
  • –> moveToState(next);
  • –> sync();
  • –> forwardPass(lifecycleOwner);
  • –> LifecycleRegistry.ObserverWithState –> dispatchEvent(owner, event);

ReflectiveGenericLifecycleObserver .java

  • –> onStateChanged()

ClassesInfoCache.java

  • –> CallbackInfo createInfo(); Reflection saves the observer’s annotated method.

MethodReference.java

  • –>invokeCallback(source, event, mWrapped);
  • –> mMethod.invoke(target); (Reflection calls the observer’s lifecycle method)

After layers of invocation and wrapping, registration eventually saves the observer’s annotated method with ** @onlifecycleEvent in a MethodReference with reflection and puts it in a HashMap. When the Activity life cycle change with layers of calls, eventually save in the collection of observer LifecycleObserver correlation method is called * * life cycle.

Does this wave of SAO operations sound familiar? That’s right! This is how EventBus manages subscriptions and events.

At the end

If you study with me, you can pay attention to my public account, ❤️ program ape Development Center ❤️, and we will share technology regularly every week. Join me and learn together!