[[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;
- class MyPresenter{
- public MyPresenter() {
- }
- void create () {
- //do something
- }
- void destroy() {
- //do something
- }
- }
- class MyActivity extends AppCompatActivity {
- private MyPresenter presenter;
- public void onCreate(...) {
- presenter= new MyPresenter ();
- presenter.create ();
- }
- public void onDestroy() {
- super.onDestroy();
- presenter.destory();
- }
- }
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 - public interface IPresenter extends LifecycleObserver {
- @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
- void onCreate(@NotNull LifecycleOwner owner);
- @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
- void onDestroy(@NotNull LifecycleOwner owner);
- @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
- void onLifecycleChanged(@NotNull LifecycleOwner owner,
- @NotNull Lifecycle.Event event);
- }
- public class BasePresenter implements IPresenter {
- private static final String TAG = "com.qingmei2.module.base.BasePresenter" ;
- @Override
- public void onLifecycleChanged(@NotNull LifecycleOwner owner, @NotNull Lifecycle.Event event) {
- }
- @Override
- public void onCreate(@NotNull LifecycleOwner owner) {
- Log.d( "tag" , "BasePresenter.onCreate" + this.getClass().toString());
- }
- @Override
- public void onDestroy(@NotNull LifecycleOwner owner) {
- Log.d( "tag" , "BasePresenter.onDestroy" + this.getClass().toString());
- }
- }
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 - public class MainActivity extends AppCompatActivity {
- private IPresenter mPresenter;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Log.d( "tag" , "onCreate" + this.getClass().toString());
- setContentView(R.layout.activity_main);
- mPresenter = new MainPresenter(this);
- getLifecycle().addObserver(mPresenter);//Add LifecycleObserver
- }
- @Override
- protected void onDestroy() {
- Log.d( "tag" , "onDestroy" + this.getClass().toString());
- super.onDestroy();
- }
- }
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- You can see the creation of ReportFragment in the onCreate method of ComponentActvitiy.
- /* ComponentActivity */
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- ...
- ReportFragment.injectIfNeededIn(this);
- ...
- }
2. getLifecycle method- /* ComponentActivity */
- private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
- @NonNull
- @Override
- public Lifecycle getLifecycle() {
- return mLifecycleRegistry;
- }
- 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. - public enum Event {
- ON_CREATE,
- ON_START,
- ON_RESUME,
- ON_PAUSE,
- ON_STOP,
- ON_DESTROY,
- ON_ANY;
- ...
- }
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. - /* ReportFragment */
- public static void injectIfNeededIn(Activity activity) {
- if (Build.VERSION.SDK_INT >= 29) {
- // On API 29+, we can register for the correct Lifecycle callbacks directly
- LifecycleCallbacks.registerIn(activity);
- }
- // Prior to API 29 and to maintain compatibility with older versions of
- // ProcessLifecycleOwner (which may not be updated when lifecycle-runtime is updated and
- // need to support activities that don't extend from FragmentActivity from support lib),
- // use a framework fragment to get the correct timing of Lifecycle events
- 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();
- }
- }
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 - Application.ActivityLifecycleCallbacks.
- @RequiresApi(29)
- static class LifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
- static void registerIn(Activity activity) {
- activity.registerActivityLifecycleCallbacks(new LifecycleCallbacks());
- }
- ...
- @Override
- public void onActivityPostCreated(@NonNull Activity activity,
- @Nullable Bundle savedInstanceState) {
- dispatch(activity, Lifecycle.Event.ON_CREATE);
- }
- ...
- }
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. - @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- dispatchCreate(mProcessListener);
- dispatch(Lifecycle.Event.ON_CREATE);
- }
- private void dispatch(@NonNull Lifecycle.Event event) {
- if (Build.VERSION.SDK_INT < 29) {
- // Only dispatch events from ReportFragment on API levels prior
- // to API 29. On API 29+, this is handled by the ActivityLifecycleCallbacks
- // added in ReportFragment.injectIfNeededIn
- dispatch(getActivity(), event);
- }
- }
- static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) {
- 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);
- }
- }
- }
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. - Lifecycle.State
- /* Lifecycle.State */
- public enum State {
- DESTROYED,
- INITIALIZED,
- CREATED,
- STARTED,
- RESUMED;
- public boolean isAtLeast(@NonNull State state) {
- return compareTo(state) >= 0;
- }
- }
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 - /* Lifecycle.Event */
- @NonNull
- public State getTargetState() {
- switch (this) {
- case ON_CREATE:
- case ON_STOP:
- return State.CREATED;
- case ON_START:
- case ON_PAUSE:
- return State.STARTED;
- case ON_RESUME:
- return State.RESUMED;
- case ON_DESTROY:
- return State.DESTROYED;
- case ON_ANY:
- break;
- }
- throw new IllegalArgumentException(this + " has no target state" );
- }
- Lifecycle.State continues to be passed down, first saved with mState, and then processed by the sync method.
- /* LifecycleRegistry */
- public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
- enforceMainThreadIfNeeded( "handleLifecycleEvent" );
- moveToState(event.getTargetState());
- }
- private void moveToState(State next ) {
- if (mState == next ) {
- return ;
- }
- //Save the state
- mState = next ;
- if (mHandlingEvent || mAddingObserverCounter != 0) {
- mNewEventOccurred = true ;
- // we will figure out what to do on upper level .
- return ;
- }
- mHandlingEvent = true ;
- sync();
- mHandlingEvent = false ;
- }
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. - /* LifecycleRegistry */
- private void sync() {
- //This is the LifecycleOwner wrapped by weak reference
- LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
- if (lifecycleOwner == null ) {
- throw new IllegalStateException( "LifecycleOwner of this LifecycleRegistry is already"
- + "garbage collected. It is too late to change lifecycle state." );
- }
- while (!isSynced()) {
- mNewEventOccurred = false ;
- // no need to check eldest for nullability, because isSynced does it for us.
- //Compare the mState saved by the previous method with the component's previous mState
- if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
- //Return execution process
- backwardPass(lifecycleOwner);
- }
- Map.Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
- if (!mNewEventOccurred && newest != null
- && mState.compareTo(newest.getValue().mState) > 0) {
- //Forward execution process
- forwardPass(lifecycleOwner);
- }
- }
- mNewEventOccurred = false ;
- }
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. - /* Lifecycle.Event */
- @Nullable
- public static Event upFrom(@NonNull State state) {
- switch (state) {
- case INITIALIZED:
- return ON_CREATE;
- case CREATED:
- return ON_START;
- case STARTED:
- return ON_RESUME;
- default :
- return null ;
- }
- }
Convert Event.upFrom and send observer.dispatchEvent. - /* LifecycleRegistry */
- private void forwardPass(LifecycleOwner lifecycleOwner) {
- Iterator<Map.Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
- mObserverMap.iteratorWithAdditions();
- while (ascendingIterator.hasNext() && !mNewEventOccurred) {
- Map.Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator. next ();
- ObserverWithState observer = entry.getValue();
- while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
- && mObserverMap. contains (entry.getKey()))) {
- pushParentState(observer.mState);
- //Conversion
- final Event event = Event.upFrom(observer.mState);
- if (event == null ) {
- throw new IllegalStateException( "no event up from " + observer.mState);
- }
- //send
- observer.dispatchEvent(lifecycleOwner, event);
- popParentState();
- }
- }
- }
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. - static class ObserverWithState {
- State mState;
- LifecycleEventObserver mLifecycleObserver;
- ObserverWithState(LifecycleObserver observer, State initialState) {
- mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
- mState = initialState;
- }
- /* Distribution life cycle status */
- void dispatchEvent(LifecycleOwner owner, Event event) {
- State newState = event.getTargetState();
- mState = min (mState, newState);
- mLifecycleObserver.onStateChanged(owner, event);
- mState = newState;
- }
- }
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" |