SoFunction
Updated on 2025-04-10

Detailed explanation of lazy loading problem of fragment under Androidx

There are already many lazy loading articles about androidx fragments on the Internet, each with its own focus. Almost all of them click sexMaxLifecycle and modify FragmentPagerAdapter. I rarely see articles that have been practiced. I would like to use this article to record the results after practice in more detail and give them to those who are destined to be destined to be.

1. Preparation work

Several lazy loading solutions for androidx are inseparable from the following packages:

  • :fragment:1.1.0-alpha07 or above, just support the setMaxLifecycle method
  • :viewpager:1.0.0 or above, if it involves fragment usage in viewpager

I used the following version in the actual test code for reference:

  • :fragment:1.2.4
  • :viewpager:1.0.0
  • FlycoTabLayout

4 activities and 5 fragments were also prepared:

  • AddShowHideFragmentActivity case displayed by add show
  • AddShowHideFragmentInFragmentActivity A fragment case nested in a fragment, displayed by add show
  • ViewPagerFragmentActivity Sliding case through ViewPager
  • ViewPagerFragmentInFragmentActivity A case nested in a fragment, displayed through ViewPager swipe
  • AddFragmentInFragment Operation add show fragment
  • ViewPagerFragmentInFragment operates the fragment of ViewPager
  • BlankFragment1 Print empty page of life cycle log1
  • BlankFragment2 Print empty page of life cycle log2
  • BlankFragment3 Print empty page of life cycle log3

Several corresponding simple layout files:

File: fragment_main.xml

Load the ViewPager control and the FrameLayout used by AddShow, and the TextView button returned after the test jump.

fragment_main.xml

<?xml version="1.0" encoding="utf-8"?>
<
  xmlns:andro
  xmlns:app="/apk/res-auto"
  xmlns:tools="/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  >

  <
    android:
    android:layout_width="match_parent"
    android:layout_height="200dp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    />

  <
    android:
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:background="@color/colorPrimary"
    app:tl_indicator_color="@color/colorAccent"
    app:tl_indicator_height="2dp"
    app:tl_indicator_width="30dp"
    app:tl_tab_space_equal="true"
    app:tl_textBold="SELECT"
    app:tl_textSelectColor="#000000"
    app:tl_textUnselectColor="#333333"
    app:layout_constraintTop_toBottomOf="@id/vp_fragment"
    app:layout_constraintLeft_toLeftOf="parent"
    />

  <FrameLayout
    android:
    android:layout_width="match_parent"
    android:layout_height="200dp"
    app:layout_constraintTop_toBottomOf="@id/tab_title"
    />

  <TextView
    android:
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:text="next"
    android:gravity="center"
    app:layout_constraintBottom_toBottomOf="parent"
    />

</>

File: activity_lazy_fragment.xml

Here is the layout of the test fragment nested case, fl_content is used to load fragment

activity_lazy_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<
  xmlns:andro
  xmlns:app="/apk/res-auto"
  xmlns:tools="/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".">

  <FrameLayout
    android:
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    />

</>

File: fragment_blank.xml

There is nothing to do with this empty fragment

fragment_blank.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:andro
  xmlns:tools="/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  >

  <TextView
    android:
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:text="" />

</FrameLayout>

2. Specific code analysis

1) ViewPager+Fragment

The most common way to use it is to slide multiple Fragments by ViewPager and directly upload the code:

activity page code

It is a simple viewpager to set the adapter and then load the fragment collection to display it

/**
  * Lazy loading of fragment in viewpager
  */
public class ViewPagerFragmentActivity extends BindActivity implements  , ,  {

  private static final String KEY_FRAGMENT_1 = "1";
  private static final String KEY_FRAGMENT_2 = "2";
  private static final String KEY_FRAGMENT_3 = "3";
  @BindView(.vp_fragment)
  ViewPager vp;
  @BindView(.tv_next)
  TextView tv_next;
  BlankFragment1 blankFragment1;
  BlankFragment2 blankFragment2;
  BlankFragment3 blankFragment3;
  List&lt;Fragment&gt; fragmentList;
  @Override
  protected int setLayoutID() {
    return .fragment_main;
  }

  @Override
  protected void initViews(Bundle savedInstanceState) {

    tv_next.setOnClickListener(new () {
      @Override
      public void onClick(View v) {
        Intent intent=new Intent(mContext, );
        startActivity(intent);
      }
    });

    if(savedInstanceState != null){
      blankFragment1 = (BlankFragment1)getSupportFragmentManager().getFragment(savedInstanceState,KEY_FRAGMENT_1);
      blankFragment2 = (BlankFragment2)getSupportFragmentManager().getFragment(savedInstanceState,KEY_FRAGMENT_2);
      blankFragment3 = (BlankFragment3)getSupportFragmentManager().getFragment(savedInstanceState,KEY_FRAGMENT_3);
    }

    fragmentList=new ArrayList&lt;&gt;();
    if (blankFragment1==null){
      (blankFragment1=("11111",""));
    }else {
      (blankFragment1);
    }
    if (blankFragment2==null){
      (blankFragment2=("22222",""));
    }else {
      (blankFragment2);
    }
    if (blankFragment3==null){
      (blankFragment3=("333333",""));
    }else {
      (blankFragment3);
    }

    (new BaseFragmentXPagerAdapter(getSupportFragmentManager(),fragmentList,null));

  }

  @Override
  public void onFragmentInteraction(Uri uri) {
  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    if(blankFragment1 != null&amp;&amp;()) {
      getSupportFragmentManager().putFragment(outState,KEY_FRAGMENT_1,blankFragment1);
    }
    if(blankFragment2 != null&amp;&amp;()){
      getSupportFragmentManager().putFragment(outState,KEY_FRAGMENT_2,blankFragment2);
    }
    if(blankFragment3 != null&amp;&amp;()){
      getSupportFragmentManager().putFragment(outState,KEY_FRAGMENT_3,blankFragment3);
    }
    (outState);
  }
}

BaseFragmentXPagerAdapter page code

The new version of FragmentPagerAdapter has 2 more constants

@Retention()
  @IntDef({BEHAVIOR_SET_USER_VISIBLE_HINT, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT})
  private @interface Behavior { }

Used in the construction method

/**
   * Constructor for {@link FragmentPagerAdapter}.
   *
   * If {@link #BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT} is passed in, then only the current
   * Fragment is in the {@link #RESUMED} state. All other fragments are capped at
   * {@link #STARTED}. If {@link #BEHAVIOR_SET_USER_VISIBLE_HINT} is passed, all
   * fragments are in the {@link #RESUMED} state and there will be callbacks to
   * {@link Fragment#setUserVisibleHint(boolean)}.
   *
   * @param fm fragment manager that will interact with this adapter
   * @param behavior determines if only current fragments are in a resumed state
   */
  public FragmentPagerAdapter(@NonNull FragmentManager fm,
      @Behavior int behavior) {
    mFragmentManager = fm;
    mBehavior = behavior;
  }

We only need to useBEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENTThis constant is fine

/**
 * support lazy init
 */
public class BaseFragmentXPagerAdapter extends FragmentPagerAdapter {

  private List<Fragment> mFragmentList = new ArrayList<>();
  private List<String> mFragmentTitleList = new ArrayList<>();

  public BaseFragmentXPagerAdapter(@NonNull FragmentManager fm,List<Fragment> fragmentList,List<String> fragmentTitleList) {
    this(fm,fragmentList,fragmentTitleList,BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
  }
  public BaseFragmentXPagerAdapter(@NonNull FragmentManager fm,List<Fragment> fragmentList,List<String> fragmentTitleList, int behavior) {
    super(fm, behavior);
    if (fragmentList!=null){
      (fragmentList);
    }
    if (fragmentTitleList!=null){
      (fragmentTitleList);
    }
  }

  public BaseFragmentXPagerAdapter(@NonNull FragmentManager fm,Fragment[] fragmentList,String[] fragmentTitleList) {
    this(fm,fragmentList,fragmentTitleList,BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
  }
  public BaseFragmentXPagerAdapter(@NonNull FragmentManager fm,Fragment[] fragmentList,String[] fragmentTitleList, int behavior) {
    super(fm, behavior);
    if (fragmentList!=null){
      for (int i = 0; i < ; i++) {
        (fragmentList[i]);
      }
    }
    if (fragmentTitleList!=null){
      for (int i = 0; i < ; i++) {
        (fragmentTitleList[i]);
      }
    }
  }

  @NonNull
  @Override
  public Fragment getItem(int position) {
    if (mFragmentList!=null&&!()){
      return (position);
    }else {
      return null;
    }
  }

  @Override
  public int getCount() {
    if (mFragmentList!=null&&!()){
      return ();
    }else {
      return 0;
    }
  }

  @Nullable
  @Override
  public CharSequence getPageTitle(int position) {
    if (mFragmentTitleList!=null&&!()&&position<()){
      return (position);
    }else {
      return null;
    }
  }
}

Finally, the life cycle log is printed and the result is confirmed. The viewPager+fragment is combined with the pagerAdapter behavior log in various situations. You can see that the new version of viewPager+pagerAdapter has been tested.The onResume lifecycle of a Fragment will only be called when the current page is displayed

First time entering the first page
ViewPagerFragmentActivity--->onCreate
ViewPagerFragmentActivity--->onStart
ViewPagerFragmentActivity--->onResume
BlankFragment1--->onAttach
BlankFragment1--->onCreate
BlankFragment2--->onAttach
BlankFragment2--->onCreate
BlankFragment1--->onViewCreated
BlankFragment1--->onActivityCreated
BlankFragment1--->onStart
BlankFragment2--->onViewCreated
BlankFragment2--->onActivityCreated
BlankFragment2--->onStart
BlankFragment1--->onResume <<============================== Current page

Slide to the second page
BlankFragment3--->onAttach
BlankFragment3--->onCreate
BlankFragment3--->onViewCreated
BlankFragment3--->onActivityCreated
BlankFragment3--->onStart
BlankFragment1--->onPause
BlankFragment2--->onResume <<============================== Current page

Lock screen
BlankFragment2--->onPause
ViewPagerFragmentActivity--->onPause
BlankFragment1--->onStop
BlankFragment2--->onStop
BlankFragment3--->onStop
ViewPagerFragmentActivity--->onStop
ViewPagerFragmentActivity--->onSaveInstanceState

Unlock the screen
ViewPagerFragmentActivity--->onRestart
BlankFragment1--->onStart
BlankFragment2--->onStart
BlankFragment3--->onStart
ViewPagerFragmentActivity--->onStart
ViewPagerFragmentActivity--->onResume
BlankFragment2--->onResume <<============================== Current page

HOME Back to desktop
BlankFragment2--->onPause
ViewPagerFragmentActivity--->onPause
BlankFragment1--->onStop
BlankFragment2--->onStop
BlankFragment3--->onStop
ViewPagerFragmentActivity--->onStop
ViewPagerFragmentActivity--->onSaveInstanceState

Return to the app page
ViewPagerFragmentActivity--->onRestart
BlankFragment1--->onStart
BlankFragment2--->onStart
BlankFragment3--->onStart
ViewPagerFragmentActivity--->onStart
ViewPagerFragmentActivity--->onResume
BlankFragment2--->onResume <<============================== Current page

Jump to a new page
BlankFragment2--->onPause
ViewPagerFragmentActivity--->onPause
MMKVActivity--->onCreate
MMKVActivity--->onStart
MMKVActivity--->onResume
BlankFragment1--->onStop
BlankFragment2--->onStop
BlankFragment3--->onStop
ViewPagerFragmentActivity--->onStop
ViewPagerFragmentActivity--->onSaveInstanceState

Return to the ViewPager page
MMKVActivity--->onPause
ViewPagerFragmentActivity--->onRestart
BlankFragment1--->onStart
BlankFragment2--->onStart
BlankFragment3--->onStart
ViewPagerFragmentActivity--->onStart
ViewPagerFragmentActivity--->onResume
BlankFragment2--->onResume <<============================== Current page
MMKVActivity--->onStop
MMKVActivity--->onDestroy

2) Fragment nests ViewPager+Fragment in Fragment

The outer activity is just add a fragment

/**
  * fragment in viewpager in fragment lazy loading
  */
public class ViewPagerFragmentInFragmentActivity extends BindActivity implements  ,, ,  {

  @Override
  protected int setLayoutID() {
    return .activity_lazy_fragment;
  }

  @Override
  protected void initViews(Bundle savedInstanceState) {
    FragmentTransaction transaction=getSupportFragmentManager().beginTransaction();
    (.fl_content, ("",""));
    ();
  }

  @Override
  public void onFragmentInteraction(Uri uri) {

  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    (outState);
  }
}

Nested fragment class, ViewPagerFragmentInFragment

/**
  * viewpager is in a fragment
  */
public class ViewPagerFragmentInFragment extends BaseFragment {
  private static final String ARG_PARAM1 = "param1";
  private static final String ARG_PARAM2 = "param2";

  private String mParam1;
  private String mParam2;

  private OnFragmentInteractionListener mListener;

  private static final String KEY_FRAGMENT_1 = "1";
  private static final String KEY_FRAGMENT_2 = "2";
  private static final String KEY_FRAGMENT_3 = "3";

  @BindView(.vp_fragment)
  ViewPager vp;
  @BindView(.tv_next)
  TextView tv_next;
  BlankFragment1 blankFragment1;
  BlankFragment2 blankFragment2;
  BlankFragment3 blankFragment3;
  List&lt;Fragment&gt; fragmentList;

  public ViewPagerFragmentInFragment() {
  }

  public static ViewPagerFragmentInFragment newInstance(String param1, String param2) {
    ViewPagerFragmentInFragment fragment = new ViewPagerFragmentInFragment();
    Bundle args = new Bundle();
    (ARG_PARAM1, param1);
    (ARG_PARAM2, param2);
    (args);
    return fragment;
  }

  @Override
  public void onSaveInstanceState(@NonNull Bundle outState) {

    if(blankFragment1 != null&amp;&amp;()) {
      ().putFragment(outState,KEY_FRAGMENT_1,blankFragment1);
    }
    if(blankFragment2 != null&amp;&amp;()){
      ().putFragment(outState,KEY_FRAGMENT_2,blankFragment2);
    }
    if(blankFragment3 != null&amp;&amp;()){
      ().putFragment(outState,KEY_FRAGMENT_3,blankFragment3);
    }
    (outState);
  }

  @Override
  public void onCreate(Bundle savedInstanceState) {
    (savedInstanceState);
    if (getArguments() != null) {
      mParam1 = getArguments().getString(ARG_PARAM1);
      mParam2 = getArguments().getString(ARG_PARAM2);
    }

  }

  @Override
  public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    (view, savedInstanceState);
    tv_next.setOnClickListener(new () {
      @Override
      public void onClick(View v) {
        Intent intent=new Intent(mContext, );
        startActivity(intent);
      }
    });

    if(savedInstanceState != null){
      blankFragment1 = (BlankFragment1)().getFragment(savedInstanceState,KEY_FRAGMENT_1);
      blankFragment2 = (BlankFragment2)().getFragment(savedInstanceState,KEY_FRAGMENT_2);
      blankFragment3 = (BlankFragment3)().getFragment(savedInstanceState,KEY_FRAGMENT_3);
    }

    fragmentList=new ArrayList&lt;&gt;();
    if (blankFragment1==null){
      (blankFragment1=("11111",""));
    }else {
      (blankFragment1);
    }
    if (blankFragment2==null){
      (blankFragment2=("22222",""));
    }else {
      (blankFragment2);
    }
    if (blankFragment3==null){
      (blankFragment3=("333333",""));
    }else {
      (blankFragment3);
    }

    (new BaseFragmentXPagerAdapter((),fragmentList,null));

  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
               Bundle savedInstanceState) {
    return (.fragment_main, container, false);
  }

  public void onButtonPressed(Uri uri) {
    if (mListener != null) {
      (uri);
    }
  }

  @Override
  public void onAttach(Context context) {
    (context);
    if (context instanceof OnFragmentInteractionListener) {
      mListener = (OnFragmentInteractionListener) context;
    } else {
      throw new RuntimeException(()
          + " must implement OnFragmentInteractionListener");
    }
  }

  @Override
  public void onDetach() {
    ();
    mListener = null;
  }

  public interface OnFragmentInteractionListener {
    void onFragmentInteraction(Uri uri);
  }
}

The actual test log can be found that even if the fragment is nested, the onResume life cycle of the Fragment will only be called when the current page is displayed:

Enter the first page for the first time
ViewPagerFragmentInFragment--->onStart
ViewPagerFragmentInFragmentActivity--->onStart
ViewPagerFragmentInFragmentActivity--->onResume
ViewPagerFragmentInFragment--->onResume
BlankFragment1--->onAttach
BlankFragment1--->onCreate
BlankFragment2--->onAttach
BlankFragment2--->onCreate
BlankFragment1--->onViewCreated
BlankFragment1--->onActivityCreated
BlankFragment1--->onStart
BlankFragment2--->onViewCreated
BlankFragment2--->onActivityCreated
BlankFragment2--->onStart
BlankFragment1--->onResume <<============================== Current page

Slide to the second page
BlankFragment3--->onAttach
BlankFragment3--->onCreate
BlankFragment3--->onViewCreated
BlankFragment3--->onActivityCreated
BlankFragment3--->onStart
BlankFragment1--->onPause
BlankFragment2--->onResume <<============================== Current page

Lock screen
ViewPagerFragmentInFragment--->onPause
BlankFragment2--->onPause
ViewPagerFragmentInFragmentActivity--->onPause
ViewPagerFragmentInFragment--->onStop
BlankFragment1--->onStop
BlankFragment2--->onStop
BlankFragment3--->onStop
ViewPagerFragmentInFragmentActivity--->onStop
ViewPagerFragmentInFragmentActivity--->onSaveInstanceState

Unlock the screen
ViewPagerFragmentInFragmentActivity--->onRestart
ViewPagerFragmentInFragment--->onStart
BlankFragment1--->onStart
BlankFragment2--->onStart
BlankFragment3--->onStart
ViewPagerFragmentInFragmentActivity--->onStart
ViewPagerFragmentInFragmentActivity--->onResume
ViewPagerFragmentInFragment--->onResume
BlankFragment2--->onResume <<============================== Current page

HOME Back to desktop
ViewPagerFragmentInFragment--->onPause
BlankFragment2--->onPause
ViewPagerFragmentInFragmentActivity--->onPause
ViewPagerFragmentInFragment--->onStop
BlankFragment1--->onStop
BlankFragment2--->onStop
BlankFragment3--->onStop
ViewPagerFragmentInFragmentActivity--->onStop
ViewPagerFragmentInFragmentActivity--->onSaveInstanceState

Return to the app page
ViewPagerFragmentInFragmentActivity--->onRestart
ViewPagerFragmentInFragment--->onStart
BlankFragment1--->onStart
BlankFragment2--->onStart
BlankFragment3--->onStart
ViewPagerFragmentInFragmentActivity--->onStart
ViewPagerFragmentInFragmentActivity--->onResume
ViewPagerFragmentInFragment--->onResume
BlankFragment2--->onResume <<============================== Current page

Jump to a new page
ViewPagerFragmentInFragment--->onPause
BlankFragment2--->onPause
ViewPagerFragmentInFragmentActivity--->onPause
MMKVActivity--->onCreate
MMKVActivity--->onStart
MMKVActivity--->onResume
ViewPagerFragmentInFragment--->onStop
BlankFragment1--->onStop
BlankFragment2--->onStop
BlankFragment3--->onStop
ViewPagerFragmentInFragmentActivity--->onStop
ViewPagerFragmentInFragmentActivity--->onSaveInstanceState

Return to the ViewPager page
MMKVActivity--->onPause
ViewPagerFragmentInFragmentActivity--->onRestart
ViewPagerFragmentInFragment--->onStart
BlankFragment1--->onStart
BlankFragment2--->onStart
BlankFragment3--->onStart
ViewPagerFragmentInFragmentActivity--->onStart
ViewPagerFragmentInFragmentActivity--->onResume
ViewPagerFragmentInFragment--->onResume
BlankFragment2--->onResume <<============================== Current page

3) Operate multiple fragments through add show hide

A detail in the activity code is to set (fragment, ) through the page of add show so that the life cycle of the fragment can smoothly reach resume;

Through the hidden page, set ((i), ) so that the hidden fragment life cycle can only reach the creation stage and cannot reach the resume method.

/**
  * Add show hide fragment to lazy load
  */
public class AddShowHideFragmentActivity extends BindActivity implements  , ,  {

  private static final String KEY_FRAGMENT_1 = "1";
  private static final String KEY_FRAGMENT_2 = "2";
  private static final String KEY_FRAGMENT_3 = "3";
  @BindView(.tab_title)
  CommonTabLayout commonTabLayout;
  @BindView(.tv_next)
  TextView tv_next;
  BlankFragment1 blankFragment1;
  BlankFragment2 blankFragment2;
  BlankFragment3 blankFragment3;
  List&lt;Fragment&gt; fragmentList;
  @Override
  protected int setLayoutID() {
    return .fragment_main;
  }

  @Override
  protected void initViews(Bundle savedInstanceState) {
    tv_next.setOnClickListener(new () {
      @Override
      public void onClick(View v) {
        Intent intent=new Intent(mContext, );
        startActivity(intent);
      }
    });
    if(savedInstanceState != null){
      blankFragment1 = (BlankFragment1)getSupportFragmentManager().getFragment(savedInstanceState,KEY_FRAGMENT_1);
      blankFragment2 = (BlankFragment2)getSupportFragmentManager().getFragment(savedInstanceState,KEY_FRAGMENT_2);
      blankFragment3 = (BlankFragment3)getSupportFragmentManager().getFragment(savedInstanceState,KEY_FRAGMENT_3);
    }
    fragmentList=new ArrayList&lt;&gt;();
    if (blankFragment1==null){
      (blankFragment1=("11111",""));
    }else {
      (blankFragment1);
    }
    if (blankFragment2==null){
      (blankFragment2=("22222",""));
    }else {
      (blankFragment2);
    }
    if (blankFragment3==null){
      (blankFragment3=("33333",""));
    }else {
      (blankFragment3);
    }
    ArrayList&lt;CustomTabEntity&gt; tabEntities = new ArrayList&lt;&gt;();
    (new TabLayoutEntity("Product 1"));
    (new TabLayoutEntity("Evaluation 2"));
    (new TabLayoutEntity("Details 3"));
    (tabEntities);
    (0);
    showFragment((0),false);
    (new OnTabSelectListener() {
      @Override
      public void onTabSelect(int position) {
        showFragment((position),false);
      }

      @Override
      public void onTabReselect(int position) {
        showFragment((position),false);
      }
    });

  }

  private void showFragment(Fragment fragment,boolean replace){
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    if (replace){
      (.fl_in_content,fragment);
    }else {
      if (!()){
        (.fl_in_content,fragment,().getSimpleName());
      }
      hideAllFragment(transaction,fragment);
      (fragment);
      (fragment, );
    }
    ();
  }
  private void hideAllFragment(FragmentTransaction transaction,Fragment withoutFragment){
    for (int i = 0; i &lt; (); i++) {
      if (!(i).equals(withoutFragment)&amp;&amp;(i).isAdded()){
        ((i));
        ((i), );
      }
    }
  }

  @Override
  public void onFragmentInteraction(Uri uri) {
  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    if(blankFragment1 != null&amp;&amp;()) {
      getSupportFragmentManager().putFragment(outState,KEY_FRAGMENT_1,blankFragment1);
    }
    if(blankFragment2 != null&amp;&amp;()){
      getSupportFragmentManager().putFragment(outState,KEY_FRAGMENT_2,blankFragment2);
    }
    if(blankFragment3 != null&amp;&amp;()){
      getSupportFragmentManager().putFragment(outState,KEY_FRAGMENT_3,blankFragment3);
    }
    (outState);
  }
}

First time entering the first page
AddShowHideFragmentActivity--->onCreate
BlankFragment1--->onAttach
BlankFragment1--->onCreate
BlankFragment1--->onViewCreated
BlankFragment1--->onActivityCreated
BlankFragment1--->onStart
AddShowHideFragmentActivity--->onStart
AddShowHideFragmentActivity--->onResume
BlankFragment1--->onResume <<============================== Current page

Click to display the second page
BlankFragment2--->onAttach
BlankFragment2--->onCreate
BlankFragment1--->onHiddenChanged=true
BlankFragment1--->onPause
BlankFragment1--->onStop
BlankFragment1--->onDestroyView
BlankFragment2--->onViewCreated
BlankFragment2--->onActivityCreated
BlankFragment2--->onStart
BlankFragment2--->onResume <<============================== Current page

Lock screen
lankFragment2--->onPause
AddShowHideFragmentActivity--->onPause
BlankFragment2--->onStop
AddShowHideFragmentActivity--->onStop
AddShowHideFragmentActivity--->onSaveInstanceState

Unlock the screen
AddShowHideFragmentActivity--->onRestart
BlankFragment2--->onStart
AddShowHideFragmentActivity--->onStart
AddShowHideFragmentActivity--->onResume
BlankFragment2--->onResume <<============================== Current page

HOME Back to desktop
BlankFragment2--->onPause
AddShowHideFragmentActivity--->onPause
BlankFragment2--->onStop
AddShowHideFragmentActivity--->onStop
AddShowHideFragmentActivity--->onSaveInstanceState

Return to the app page
AddShowHideFragmentActivity--->onRestart
BlankFragment2--->onStart
AddShowHideFragmentActivity--->onStart
AddShowHideFragmentActivity--->onResume
BlankFragment2--->onResume <<============================== Current page

Jump to a new page
BlankFragment2--->onPause
AddShowHideFragmentActivity--->onPause
MMKVActivity--->onCreate
MMKVActivity--->onStart
MMKVActivity--->onResume
BlankFragment2--->onStop
AddShowHideFragmentActivity--->onStop
AddShowHideFragmentActivity--->onSaveInstanceState

Return to the ViewPager page
MMKVActivity--->onPause
AddShowHideFragmentActivity--->onRestart
BlankFragment2--->onStart
AddShowHideFragmentActivity--->onStart
AddShowHideFragmentActivity--->onResume
BlankFragment2--->onResume <<============================== Current page

4) Fragment nests add show hide Fragment within Fragment

The outer activity is just add a fragment

/**
  * fragment in viewpager in fragment lazy loading
  */
public class AddShowHideFragmentInFragmentActivity extends BindActivity implements  ,, ,  {

  @Override
  protected int setLayoutID() {
    return .activity_lazy_fragment;
  }

  @Override
  protected void initViews(Bundle savedInstanceState) {
    FragmentTransaction transaction=getSupportFragmentManager().beginTransaction();
    (.fl_content,("",""));
    ();
  }

  @Override
  public void onFragmentInteraction(Uri uri) {

  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    (outState);
  }
}

The internal fragment code is as follows

/**
  * The fragment displayed by add hide show is nested inside the outer fragment
  */
public class AddFragmentInFragment extends BaseFragment {

  private static final String ARG_PARAM1 = "param1";
  private static final String ARG_PARAM2 = "param2";

  private String mParam1;
  private String mParam2;

  private OnFragmentInteractionListener mListener;

  private static final String KEY_FRAGMENT_1 = "1";
  private static final String KEY_FRAGMENT_2 = "2";
  private static final String KEY_FRAGMENT_3 = "3";

  @BindView(.tab_title)
  CommonTabLayout commonTabLayout;
  @BindView(.tv_next)
  TextView tv_next;
  BlankFragment1 blankFragment1;
  BlankFragment2 blankFragment2;
  BlankFragment3 blankFragment3;
  List&lt;Fragment&gt; fragmentList;

  public AddFragmentInFragment() {
  }

  public static AddFragmentInFragment newInstance(String param1, String param2) {
    AddFragmentInFragment fragment = new AddFragmentInFragment();
    Bundle args = new Bundle();
    (ARG_PARAM1, param1);
    (ARG_PARAM2, param2);
    (args);
    return fragment;
  }

  @Override
  public void onSaveInstanceState(@NonNull Bundle outState) {
    if(blankFragment1 != null&amp;&amp;()) {
      ().putFragment(outState,KEY_FRAGMENT_1,blankFragment1);
    }
    if(blankFragment2 != null&amp;&amp;()){
      ().putFragment(outState,KEY_FRAGMENT_2,blankFragment2);
    }
    if(blankFragment3 != null&amp;&amp;()){
      ().putFragment(outState,KEY_FRAGMENT_3,blankFragment3);
    }
    (outState);
  }

  @Override
  public void onCreate(Bundle savedInstanceState) {
    (savedInstanceState);
    if (getArguments() != null) {
      mParam1 = getArguments().getString(ARG_PARAM1);
      mParam2 = getArguments().getString(ARG_PARAM2);
    }

  }

  @Override
  public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    (view, savedInstanceState);
    tv_next.setOnClickListener(new () {
      @Override
      public void onClick(View v) {
        Intent intent=new Intent(mContext, );
        startActivity(intent);
      }
    });
    if(savedInstanceState != null){
      blankFragment1 = (BlankFragment1)().getFragment(savedInstanceState,KEY_FRAGMENT_1);
      blankFragment2 = (BlankFragment2)().getFragment(savedInstanceState,KEY_FRAGMENT_2);
      blankFragment3 = (BlankFragment3)().getFragment(savedInstanceState,KEY_FRAGMENT_3);
    }
    fragmentList=new ArrayList&lt;&gt;();
    if (blankFragment1==null){
      (blankFragment1=("11111",""));
    }else {
      (blankFragment1);
    }
    if (blankFragment2==null){
      (blankFragment2=("222222",""));
    }else {
      (blankFragment2);
    }
    if (blankFragment3==null){
      (blankFragment3=("3333333",""));
    }else {
      (blankFragment3);
    }

    ArrayList&lt;CustomTabEntity&gt; tabEntities = new ArrayList&lt;&gt;();
    (new TabLayoutEntity("Product 1"));
    (new TabLayoutEntity("Evaluation 2"));
    (new TabLayoutEntity("Details 3"));
    (tabEntities);
    (0);
    showFragment((0),false);
    (new OnTabSelectListener() {
      @Override
      public void onTabSelect(int position) {
        showFragment((position),false);
      }

      @Override
      public void onTabReselect(int position) {
        showFragment((position),false);
      }
    });

  }

  private void showFragment(Fragment fragment,boolean replace){
    FragmentTransaction transaction = ().beginTransaction();
    if (replace){
      (.fl_in_content,fragment);
    }else {
      if (!()){
        (.fl_in_content,fragment,().getSimpleName());
      }
      hideAllFragment(transaction,fragment);
      (fragment);
      (fragment, );
    }
    ();
  }
  private void hideAllFragment(FragmentTransaction transaction,Fragment withoutFragment){
    for (int i = 0; i &lt; (); i++) {
      if (!(i).equals(withoutFragment)&amp;&amp;(i).isAdded()){
        ((i));
        ((i), );
      }
    }
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
               Bundle savedInstanceState) {
    return (.fragment_main, container, false);
  }

  public void onButtonPressed(Uri uri) {
    if (mListener != null) {
      (uri);
    }
  }

  @Override
  public void onAttach(Context context) {
    (context);
    if (context instanceof OnFragmentInteractionListener) {
      mListener = (OnFragmentInteractionListener) context;
    } else {
      throw new RuntimeException(()
          + " must implement OnFragmentInteractionListener");
    }
  }

  @Override
  public void onDetach() {
    ();
    mListener = null;
  }

  public interface OnFragmentInteractionListener {
    void onFragmentInteraction(Uri uri);
  }
}

The actual test log can be found that even if the fragment is nested, the onResume life cycle of the Fragment will only be called when the current page is displayed:

First time entering the first page
AddShowHideFragmentInFragmentActivity--->onCreate
AddFragmentInFragment--->onAttach
AddFragmentInFragment--->onCreate
AddFragmentInFragment--->onViewCreated
AddFragmentInFragment--->onActivityCreated
BlankFragment1--->onAttach
BlankFragment1--->onCreate
BlankFragment1--->onViewCreated
BlankFragment1--->onActivityCreated
AddFragmentInFragment--->onStart
BlankFragment1--->onStart
AddShowHideFragmentInFragmentActivity--->onStart
AddShowHideFragmentInFragmentActivity--->onResume
AddFragmentInFragment--->onResume
BlankFragment1--->onResume <<============================== Current page

Click to display the second page
BlankFragment2--->onAttach
BlankFragment2--->onCreate
BlankFragment1--->onHiddenChanged=true
BlankFragment1--->onPause
BlankFragment1--->onStop
BlankFragment1--->onDestroyView
BlankFragment2--->onViewCreated
BlankFragment2--->onActivityCreated
BlankFragment2--->onStart
BlankFragment2--->onResume <<============================== Current page

Lock screen
AddFragmentInFragment--->onPause
BlankFragment2--->onPause
AddShowHideFragmentInFragmentActivity--->onPause
AddFragmentInFragment--->onStop
BlankFragment2--->onStop
AddShowHideFragmentInFragmentActivity--->onStop
AddShowHideFragmentInFragmentActivity--->onSaveInstanceState

Unlock the screen
AddShowHideFragmentInFragmentActivity--->onRestart
AddFragmentInFragment--->onStart
BlankFragment2--->onStart
AddShowHideFragmentInFragmentActivity--->onStart
AddShowHideFragmentInFragmentActivity--->onResume
AddFragmentInFragment--->onResume
BlankFragment2--->onResume <<============================== Current page
HOME Back to desktop
AddFragmentInFragment--->onPause
BlankFragment2--->onPause
AddShowHideFragmentInFragmentActivity--->onPause
AddFragmentInFragment--->onStop
BlankFragment2--->onStop
AddShowHideFragmentInFragmentActivity--->onStop
AddShowHideFragmentInFragmentActivity--->onSaveInstanceState

Return to the app page
AddShowHideFragmentInFragmentActivity--->onRestart
AddFragmentInFragment--->onStart
BlankFragment2--->onStart
AddShowHideFragmentInFragmentActivity--->onStart
AddShowHideFragmentInFragmentActivity--->onResume
AddFragmentInFragment--->onResume
BlankFragment2--->onResume <<============================== Current page

Jump to a new page
AddFragmentInFragment--->onPause
BlankFragment2--->onPause
AddShowHideFragmentInFragmentActivity--->onPause
MMKVActivity--->onCreate
MMKVActivity--->onStart
MMKVActivity--->onResume
AddFragmentInFragment--->onStop
BlankFragment2--->onStop
AddShowHideFragmentInFragmentActivity--->onStop
AddShowHideFragmentInFragmentActivity--->onSaveInstanceState

Return to the current page
MMKVActivity--->onPause
AddShowHideFragmentInFragmentActivity--->onRestart
AddFragmentInFragment--->onStart
BlankFragment2--->onStart
AddShowHideFragmentInFragmentActivity--->onStart
AddShowHideFragmentInFragmentActivity--->onResume
AddFragmentInFragment--->onResume
BlankFragment2--->onResume <<============================== Current page

3. Summary

The above lists four different usage scenarios and various common operation logics. In addition to ensuring that the page only displays the onResume lifecycle function when it is displayed as the current page, the UI exception overlapping display after fragment destruction is also solved through the saveState method.

This is the article about the detailed explanation of the lazy lazy loading problem of fragment under Androidx. For more related androidx fragment lazy lazy loading content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!