preface

While writing a ViewPager2 article, I noticed that the latest Fragment code had eliminated the setUserVisibleHint method in favor of the setMaxLifecycle method, which means to set the maximum life cycle. It is not possible to set the life cycle of Fragment directly. It is necessary to intervene indirectly through add, attach, remove, detach, show and hide methods. This function is intended to briefly introduce the principle and effect of setMaxLifecycle.

Reading Guide:

  • This article is based onAndroidx 1.1.0 - alpha07Version of thefragmentCarry on, also supportsetMaxLifecycleMinimum version of
  • This article will be based onFragmentPagerAdapterforsetMaxLifecycleExample Application Explanation

Basic introduction

SetMaxLifecycle is defined within the FragmentTransaction in parallel with the add, attach, remove, detach, show, hide methods;

FragmentTransaction

public FragmentTransaction setMaxLifecycle(@NonNull Fragment fragment,
        @NonNull Lifecycle.State state) {
    addOp(new Op(OP_SET_MAX_LIFECYCLE, fragment, state));
    return this;
}
Copy the code

Parameter interpretation:

  • fragmentThat’s the Fragment object that you want to operate on, and that’s the prerequisitefragmentMust have been added toFragmentManager;
  • state Lifecycle.StateEnumeration type, which can be used only if it is at leastLifecycle.State.CREATED, otherwise, submitted to theIllegalArgumentExceptionabnormal

There are five states at Lifecycle. The minimum requirement is lifecycle.state. CREATED, so the available parameters are CREATED, STARTED, RESUMED, State and Lifecycle.

Life cycle status understanding

In the Fragment, there are five states defined. The State is not as described above in Lifecycle.State, but the logic is basically the same;

  • INITIALIZINGThe initial state
  • CREATEDCreated Status
  • ACTIVITY_CREATEDFully created, but not started
  • STARTEDCreate and start, but cannot be performed
  • RESUMEDCreate is up and operational

This article only explains the three states: CREATED, STARTED, and RESUMED. Since mState and Lifecycle.State defined in Fragment are not the same, they are considered the same concept in this article.

Corresponds to the life cycle

I’m sure you all know that the Fragment lifecycle has onDestory, onStop and other methods, but there are not so many states, so how to identify the state and the corresponding relationship, the corresponding relationship is given below;

First, I treat the lifecycle methods from onCreate->onCretateView->onStart->onResume->onPause->onStop-> onDestoryView->onDestory as ordering from small to large;

Similarly, we consider the life cycle state CREATED->STARTED->RESUMED to rank from small to large;

  • CREATED a state

CREATED refers to the CREATED state. In a narrow sense, the lifecycle method goes to onCreate. If the current fragment state is greater than CREATED, then the lifecycle method goes to onDestoryView. So there are two cases of CREATED;

  • STARTED state

If the fragment’s status is greater than STARTED, the fragment’s life cycle method goes to onPause. If the fragment’s status is less than CREATED, the fragment’s life cycle method goes to onStart.

  • The RESUMED state

RESUMED indicates a special state, which only represents the onResume state. No matter how big or small, it eventually stays in the onResume state.

The above life-cycle state torsion conclusions are based onFragmentManagerImpl.moveToState()Method extraction, if misleading, please advise

How to use

SetMaxLifecycle can be used alone or in combination with add and other methods. First, we analyze the state changes when add is executed separately:

Perform the add operation separately

FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
fragmentTransaction.add(R.id.frame_layout,cardFragment);
fragmentTransaction.commit();
Copy the code

Add cooperate setMaxLifecycle (Lifecycle. State. CREATED)

FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
fragmentTransaction.add(R.id.frame_layout,cardFragment);
fragmentTransaction.setMaxLifecycle(cardFragment, Lifecycle.State.CREATED);
fragmentTransaction.commit();
Copy the code

Add cooperate setMaxLifecycle (Lifecycle. State. STARTED)

FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
fragmentTransaction.add(R.id.frame_layout,cardFragment);
fragmentTransaction.setMaxLifecycle(cardFragment, Lifecycle.State.STARTED);
fragmentTransaction.commit();
Copy the code

Add cooperate setMaxLifecycle (Lifecycle. State. RESUMED)

FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
fragmentTransaction.add(R.id.frame_layout,cardFragment);
fragmentTransaction.setMaxLifecycle(cardFragment, Lifecycle.State.RESUMED);
fragmentTransaction.commit();
Copy the code

Use setMaxLifecycle alone

FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.setMaxLifecycle(cardFragment, xxx);
fragmentTransaction.commit();
Copy the code
  • rightRESUMEDStatus of the Fragment to perform operationsCREATEDoperation

  • rightRESUMEDStatus of the Fragment to perform operationsSTARTEDoperation

  • rightRESUMEDStatus of the Fragment to perform operationsCREATEDOperation, in progressSTARTEDoperation

For space reasons, I don’t want to cover all the combinations. As long as you understand the life cycle states, whether they are up or down, whether they are combined or used alone, you can control them.

FragmentPagerAdapter changes

Since setMaxLifecycle introduces the life cycle setting and replaces the old setUserVisibleHint method, it is also adapted in the FragmentPagerAdapter

FragmentPagerAdapter

public static final int BEHAVIOR_SET_USER_VISIBLE_HINT = 0;
public static final int BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1;

private final int mBehavior;

public FragmentPagerAdapter(@NonNull FragmentManager fm) {
    this(fm, BEHAVIOR_SET_USER_VISIBLE_HINT);
}

public FragmentPagerAdapter(@NonNull FragmentManager fm,@Behavior int behavior) {
    mFragmentManager = fm;
    mBehavior = behavior;
}
Copy the code

The latest FragmentPagerAdapter uses an mBehavior to control either setUserVisibleHint or setMaxLifecycle. MBehavior is specified in the constructor;

Replace setUserVisibleHint(false) with setMaxLifecycle(mCurrentPrimaryItem, Lifecycle.state.started) Replace setUserVisibleHint(true) with setMaxLifecycle(fragment, Lifecycle.state.resumed);

Why should lifecy.state.started be used? Add +Lifecycle.State.STARTED and attach+Lifecycle.

The end result is an invisible Fragment that only goes through the life cycleonStartMethod, won’t goonResumeMethods;

The new scheme is lazily loaded

In the past, we used setUserVisibleHint to control lazy Fragment loading. In the latest version of FragmentPagerAdapter, we can switch the BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT mode. In FragmentonResume, more display logic;

To switch to the BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT mode, the BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT mode is BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT mode.

new FragmentPagerAdapter(getSupportFragmentManager(),FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)
Copy the code

conclusion

What does this article actually say? Let’s summarize:

Use setMaxLifecycle to further control the lifecycle of the Fragment. This is a supplement to add, attach, and other commands.

Secondly, this function can be used in the official control, improving the use experience of ViewPager+Fragment, lazy loading attention points;

Finally encourage everyone (mainly their own) to look at the source code, tamp the foundation, can not change should be the end of this article.