Source code advanced analysis of the lifecycle component principle

Source code advanced analysis of the lifecycle component principle

[[421728]]

Preface

How to use the classes provided by the android.arch.lifecycle package to control the lifecycle of data, listeners, etc. At the same time, the lifecycle of LiveData and ViewModel also depends on the Lifecycle framework;

Today we will talk about the implementation principle of lifecycle and analyze it

1. Why introduce Lifecycle?

1. No Lifecycle approach introduced

  • When dealing with the life cycle of Activity or Fragment components, it is inevitable to encounter such problems;
  • Initialize some members in the Activity's onCreate() (such as Presenter in the MVP architecture, or AudioManager, MediaPlayer, etc.), then process these members accordingly in onStop, and release these resources in onDestroy, which may cause our code to look like this;
  1. class MyPresenter{
  2. public MyPresenter() {
  3. }
  4. void create () {
  5. //do something
  6. }
  7. void destroy() {
  8. //do something
  9. }
  10. }
  11. class MyActivity extends AppCompatActivity {
  12. private MyPresenter presenter;
  13. public void onCreate(...) {
  14. presenter= new MyPresenter ();
  15. presenter.create ();
  16. }
  17. public void onDestroy() {
  18. super.onDestroy();
  19. presenter.destory();
  20. }
  21. }

There is nothing wrong with the code, but the key problem is that in the actual production environment, such code will be very complicated. You will end up with too many similar calls and the onCreate() and onDestroy() methods will become very bloated;

2. Introducing Lifecycle practices

Lifecycle is a class that holds information about the lifecycle state of a component (such as an Activity or Fragment) and allows other objects to observe this state;

The code is as follows:

Prestener inherits the LifecycleObserver interface

  1. public interface IPresenter extends LifecycleObserver {
  2. @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
  3. void onCreate(@NotNull LifecycleOwner owner);
  4. @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
  5. void onDestroy(@NotNull LifecycleOwner owner);
  6. @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
  7. void onLifecycleChanged(@NotNull LifecycleOwner owner,
  8. @NotNull Lifecycle.Event event);
  9. }
  10. public class BasePresenter implements IPresenter {
  11. private static final String TAG = "com.qingmei2.module.base.BasePresenter" ;
  12. @Override
  13. public void onLifecycleChanged(@NotNull LifecycleOwner owner, @NotNull Lifecycle.Event event) {
  14. }
  15. @Override
  16. public void onCreate(@NotNull LifecycleOwner owner) {
  17. Log.d( "tag" , "BasePresenter.onCreate" + this.getClass().toString());
  18. }
  19. @Override
  20. public void onDestroy(@NotNull LifecycleOwner owner) {
  21. Log.d( "tag" , "BasePresenter.onDestroy" + this.getClass().toString());
  22. }
  23. }

Directly list all the life cycle events that I want to observe in Presenter, and then encapsulate them in BasePresenter, so that each subclass of BasePresenter can perceive the life cycle events corresponding to the Activity container, and correspond to the corresponding behavior in the method overridden by the subclass

Add Observer to Activity/Fragment container

  1. public class MainActivity extends AppCompatActivity {
  2. private IPresenter mPresenter;
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. Log.d( "tag" , "onCreate" + this.getClass().toString());
  7. setContentView(R.layout.activity_main);
  8. mPresenter = new MainPresenter(this);
  9. getLifecycle().addObserver(mPresenter);//Add LifecycleObserver
  10. }
  11. @Override
  12. protected void onDestroy() {
  13. Log.d( "tag" , "onDestroy" + this.getClass().toString());
  14. super.onDestroy();
  15. }
  16. }

Whenever the Activity undergoes a corresponding life cycle change, the Presenter will execute the method annotated with the corresponding event

2. In-depth analysis of Lifecycle principles

To obtain Lifecycle in Activity, you actually obtain it through the Activity's parent class ComponentActivity. The parent class implements the LifecycleOwner interface, so you can obtain Lifecycle. Finally, register LifecycleObserver to get the lifecycle callback.

1. onCreate

  1. You can see the creation of ReportFragment in the onCreate method of ComponentActvitiy.
  2. /* ComponentActivity */
  3. @Override
  4. protected void onCreate(@Nullable Bundle savedInstanceState) {
  5. ...
  6. ReportFragment.injectIfNeededIn(this);
  7. ...
  8. }

2. getLifecycle method

  1. /* ComponentActivity */
  2. private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
  3. @NonNull
  4. @Override
  5. public Lifecycle getLifecycle() {
  6. return mLifecycleRegistry;
  7. }
  8. Life

3. Lifecycle.Event

Lifecycle.Event is an enumeration class. The lifecycle Event here is not Fragment's, and will be used in the subsequent lifecycle processing.

  1. public enum Event {
  2. ON_CREATE,
  3. ON_START,
  4. ON_RESUME,
  5. ON_PAUSE,
  6. ON_STOP,
  7. ON_DESTROY,
  8. ON_ANY;
  9. ...
  10. }

4. Creation of ReportFragment

ReportFragment is a fragment without an interface. If you have learned about the principles of Glide, you should also know this method, which is to perceive the life cycle through the invisible fragment, so that users do not need to consider the life cycle issues.

In SDK 29 and above, LifecycleCallbacks.registerIn(activity) is used.

  1. /* ReportFragment */
  2. public   static void injectIfNeededIn(Activity activity) {
  3. if (Build.VERSION.SDK_INT >= 29) {
  4. // On API 29+, we can register for the correct Lifecycle callbacks directly
  5. LifecycleCallbacks.registerIn(activity);
  6. }
  7. // Prior   to API 29 and   to maintain compatibility with older versions of  
  8. // ProcessLifecycleOwner (which may not be updated when lifecycle-runtime is updated and  
  9. // need to support activities that don't extend from FragmentActivity from support lib),
  10. // use a framework fragment to get the correct timing of Lifecycle events
  11. android.app.FragmentManager manager = activity.getFragmentManager();
  12. if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null ) {
  13. manager.beginTransaction(). add (new ReportFragment(), REPORT_FRAGMENT_TAG) .commit ();
  14. //Hopefully, we are the first   to make a transaction .
  15. manager.executePendingTransactions();
  16. }
  17. }

5. LifecycleCallbacks.registerIn(activity)

LifecycleCallbacks implements the Application.ActivityLifecycleCallbacks interface. In SDK 29 and above, the lifecycle distribution is distributed by the Application, and the activity can be called back after registration.

The famous LeakCanary also uses the monitoring Activity life cycle

  1. Application.ActivityLifecycleCallbacks.
  2. @RequiresApi(29)
  3. static class LifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
  4. static void registerIn(Activity activity) {
  5. activity.registerActivityLifecycleCallbacks(new LifecycleCallbacks());
  6. }
  7. ...
  8. @Override
  9. public void onActivityPostCreated(@NonNull Activity activity,
  10. @Nullable Bundle savedInstanceState) {
  11. dispatch(activity, Lifecycle.Event.ON_CREATE);
  12. }
  13. ...
  14. }

6. ReportFragment.dispatch version compatibility

If the SDK version is less than 29, the dispatch method will be called in each life cycle method of ReportFragment.

For example, onActivityCreated.

Anyway, whether you use LifecycleCallbacks.registerIn(activity) or Fragment's lifecycle callback, it will be dispatched in the end.

  1. @Override
  2. public void onActivityCreated(Bundle savedInstanceState) {
  3. super.onActivityCreated(savedInstanceState);
  4. dispatchCreate(mProcessListener);
  5. dispatch(Lifecycle.Event.ON_CREATE);
  6. }
  7. private void dispatch(@NonNull Lifecycle.Event event) {
  8. if (Build.VERSION.SDK_INT < 29) {
  9. // Only dispatch events from ReportFragment on API levels prior  
  10. // to API 29. On API 29+, this is handled by the ActivityLifecycleCallbacks
  11. // added in ReportFragment.injectIfNeededIn
  12. dispatch(getActivity(), event);
  13. }
  14. }
  15. static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) {
  16. if (activity instanceof LifecycleRegistryOwner) {
  17. ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
  18. return ;
  19. }
  20. if (activity instanceof LifecycleOwner) {
  21. Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
  22. if (lifecycle instanceof LifecycleRegistry) {
  23. ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
  24. }
  25. }
  26. }

7. Lifecycle.State

There are only 5 states but more than 5 life cycles, so when Google designed it, they created the process in the forward direction and destroyed the process in the reverse direction.

  1. Lifecycle.State
  2. /* Lifecycle.State */
  3. public enum State {
  4. DESTROYED,
  5. INITIALIZED,
  6. CREATED,
  7. STARTED,
  8. RESUMED;
  9. public boolean isAtLeast(@NonNull State state) {
  10. return compareTo(state) >= 0;
  11. }
  12. }

8. handleLifecycleEvent

LifecycleRegistryOwner also inherits LifecycleOwner, so they will eventually execute the handleLifecycleEvent method of LifecycleRegistry.

Just process Lifecycle.Event and convert it into Lifecycle.State

  1. /* Lifecycle.Event */
  2. @NonNull
  3. public State getTargetState() {
  4. switch (this) {
  5. case ON_CREATE:
  6. case ON_STOP:
  7. return State.CREATED;
  8. case ON_START:
  9. case ON_PAUSE:
  10. return State.STARTED;
  11. case ON_RESUME:
  12. return State.RESUMED;
  13. case ON_DESTROY:
  14. return State.DESTROYED;
  15. case ON_ANY:
  16. break;
  17. }
  18. throw new IllegalArgumentException(this + " has no target state" );
  19. }
  20. Lifecycle.State continues to be passed down, first saved with mState, and then processed by the sync method.
  21. /* LifecycleRegistry */
  22. public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
  23. enforceMainThreadIfNeeded( "handleLifecycleEvent" );
  24. moveToState(event.getTargetState());
  25. }
  26. private void moveToState(State next ) {
  27. if (mState == next ) {
  28. return ;
  29. }
  30. //Save the state
  31. mState = next ;
  32. if (mHandlingEvent || mAddingObserverCounter != 0) {
  33. mNewEventOccurred = true ;
  34. // we will figure out what to do on   upper   level .
  35. return ;
  36. }
  37. mHandlingEvent = true ;
  38. sync();
  39. mHandlingEvent = false ;
  40. }

9. sync

Here we use the mState saved by the previous method for comparison to determine whether to execute the life cycle forward or reverse.

  1. /* LifecycleRegistry */
  2. private void sync() {
  3. //This is the LifecycleOwner wrapped by weak reference
  4. LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
  5. if (lifecycleOwner == null ) {
  6. throw new IllegalStateException( "LifecycleOwner of this LifecycleRegistry is already"  
  7. + "garbage collected. It is too late to change lifecycle state." );
  8. }
  9. while (!isSynced()) {
  10. mNewEventOccurred = false ;
  11. // no need to   check eldest for nullability, because isSynced does it for us.
  12. //Compare the mState saved by the previous method with the component's previous mState
  13. if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
  14. //Return execution process
  15. backwardPass(lifecycleOwner);
  16. }
  17. Map.Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
  18. if (!mNewEventOccurred && newest != null  
  19. && mState.compareTo(newest.getValue().mState) > 0) {
  20. //Forward execution process
  21. forwardPass(lifecycleOwner);
  22. }
  23. }
  24. mNewEventOccurred = false ;
  25. }

10. forwardPass

The reverse logic is similar, except that backwardPass is executed to convert Stata first and then observer.dispatchEvent is executed.

Here, Lifecycle.State is converted back to Lifecycle.Event and then distributed to the observer.

  1. /* Lifecycle.Event */
  2. @Nullable
  3. public   static Event upFrom(@NonNull State state) {
  4. switch (state) {
  5. case INITIALIZED:
  6. return ON_CREATE;
  7. case CREATED:
  8. return ON_START;
  9. case STARTED:
  10. return ON_RESUME;
  11. default :
  12. return   null ;
  13. }
  14. }

Convert Event.upFrom and send observer.dispatchEvent.

  1. /* LifecycleRegistry */
  2. private void forwardPass(LifecycleOwner lifecycleOwner) {
  3. Iterator<Map.Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
  4. mObserverMap.iteratorWithAdditions();
  5. while (ascendingIterator.hasNext() && !mNewEventOccurred) {
  6. Map.Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator. next ();
  7. ObserverWithState observer = entry.getValue();
  8. while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
  9. && mObserverMap. contains (entry.getKey()))) {
  10. pushParentState(observer.mState);
  11. //Conversion
  12. final Event event = Event.upFrom(observer.mState);
  13. if (event == null ) {
  14. throw new IllegalStateException( "no event up from " + observer.mState);
  15. }
  16. //send
  17. observer.dispatchEvent(lifecycleOwner, event);
  18. popParentState();
  19. }
  20. }
  21. }

11. Send life cycle status

ObserverWithState sends out Lifecycle.Event, and that's it. Any place that has a registered subscription relationship can receive it.

  1. static class ObserverWithState {
  2. State mState;
  3. LifecycleEventObserver mLifecycleObserver;
  4. ObserverWithState(LifecycleObserver observer, State initialState) {
  5. mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
  6. mState = initialState;
  7. }
  8. /* Distribution life cycle status */
  9. void dispatchEvent(LifecycleOwner owner, Event event) {
  10. State newState = event.getTargetState();
  11. mState = min (mState, newState);
  12. mLifecycleObserver.onStateChanged(owner, event);
  13. mState = newState;
  14. }
  15. }

The principle is relatively clear: Activity/Fragment implements the LifecycleOwner interface, distributes the event Lifecycle.Event in the corresponding lifecycle through LifecycleRegistry, and calls back to the corresponding subscription method of the lifecycle observer LifecycleObserver


Summarize

Lifecycle still has its merits. Compared with the coordination between other architecture components, Lifecycle is simpler and more independent.

LifecycleObserver interface (Lifecycle observer): The class that implements this interface can be registered through the addObserver(LifecycleObserver o) method of the LifecycleOwner class through annotations. After registration, LifecycleObserver can observe the lifecycle events of LifecycleOwner;

LifecycleOwner interface (Lifecycle holder): The class that implements this interface holds the lifecycle (Lifecycle object). Changes in the lifecycle (Lifecycle object) of this interface will be observed by its registered observer LifecycleObserver and trigger its corresponding events;

Lifecycle (lifecycle): Unlike LifecycleOwner, LifecycleOwner itself holds the Lifecycle object, and LifecycleOwner obtains the internal Lifecycle object through its Lifecycle getLifecycle() interface;

State (the current state of the life cycle);

Event (the event corresponding to the current life cycle change). When the Lifecycle changes, such as entering onCreate, the ON_CREATE event will be automatically issued;

Some knowledge points about the official architecture will be introduced later;

This article is reproduced from the WeChat public account "Android Development Programming"

<<:  The launch of important features of iOS 15 has been delayed, and Apple is being criticized by the whole network

>>:  When using WeChat Pay, remember to turn on these 4 switches to make the money in WeChat safer

Recommend

Lu Ban, you'd better give up!

Luban ’s business is not suitable at all for smal...

Is dopamine, which is so popular, really the "code for happiness"?

© MIT News Leviathan Press: A few years ago, I wa...

Top 10 advertising models during the epidemic

If we were to find a keyword to describe the livi...

How to improve ROI? Internet marketing combination methodology!

This article will focus on the general Internet m...