preface

Most of the home page architecture of APP is Tab + Fragment. When the program is abnormal, it will automatically recover, or after the APP is restored in the background for a long time, the Fragment will have double shadow (overlap) and other problems. Of course, some people do not care about the page level, each Fragment view has a background, may not be detected, but does not mean that there is no. However, many fragments are used improperly or even display a blank screen.

1 Double shadow (overlap)

1.1 Trigger Cause

The onSaveInstanceState method is called to save data during an abnormal exit, including the View Hierarchy, where the Activity is rebuilt. The onRestoreInstanceState method is called, the Fragment that was instantiated before will still appear in the Activity, and the normal life flow will follow, In onCreate, FragmentTransaction adds a fragment to it again, and the hide() and show() methods are no longer valid for the fragment that was previously saved. These factors lead to multiple fragments overlapping

1.2 Debugging

  • If you’re not sure if your app has this problem, check to see if your fragment has a background, and if so, delete it
  • Mobile phone “Settings” – “Developer options” – Open “Do not Retain Activities” (mainly used to simulate activities being recycled in time)
  • Switch the APP to the background and open it again. Click a different TAB to switch the Fragment, open other pages, and then switch TAB
  • If there is ghosting, please continue to see the solution below, if not, congratulations, your code is perfect, I hope you can provide a better solution

1.3 Solution

1.3.1 Checking whether savedInstanceState is Null in onCreate (Not recommended)

If savedInstanceState is not null, the Activity has a saved instance. Select * from selectedFragment where xx.getClass ().getSimplename () is a Tag

private void selectedFragment(int position) {
        mPosition = position;
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        hideFragment(transaction);
        switch (position) {
            caseZero:if (fragment1 == null) {
                    fragment1 = new Fragment1();
                    transaction.add(R.id.fl_content, fragment1,fragment1.getClass().getSimpleName());
                } else {
                    transaction.show(fragment1);
                }
                break;
            case 1:
                if (fragment2 == null) {
                    fragment2 = new Fragment2();
                    transaction.add(R.id.fl_content, fragment2,fragment2.getClass().getSimpleName());
                } else {
                    transaction.show(fragment2);
                }
                break;
            case 2:
                if (fragment3 == null) {
                    fragment3 = new Fragment3();
                    transaction.add(R.id.fl_content, fragment3,fragment3.getClass().getSimpleName());
                } else {
                    transaction.show(fragment3);
                }
                break;
            case 3:
                if (fragment4 == null) {
                    fragment4 = new Fragment4();
                    transaction.add(R.id.fl_content, fragment4,fragment4.getClass().getSimpleName());
                } else {
                    transaction.show(fragment4);
                }
                break;
            default:
        }
        transaction.commitAllowingStateLoss();
    }

Copy the code

OnCreate method code

@Override protected void onCreate(Bundle savedInstanceState) { super.initData(savedInstanceState); // If the fragment is not null, it is dead and resurrected. Remove existing fragmentsif(savedInstanceState ! = null) { FragmentTransaction mTransaction = getSupportFragmentManager().beginTransaction(); mTransaction.remove(mManager.findFragmentByTag(Fragment4.class.getSimpleName())); mTransaction.remove(mManager.findFragmentByTag(Fragment3.class.getSimpleName())); mTransaction.remove(mManager.findFragmentByTag(Fragment2.class.getSimpleName())); mTransaction.remove(mManager.findFragmentByTag(Fragment1.class.getSimpleName())); mTransaction.commitAllowingStateLoss(); } selectedFragment(mPosition); . }Copy the code
1.3.2 Overriding the onSaveInstanceState onRestoreInstanceState method (recommended)

There is no need to add a Tag to the Fragment to keep the original implementation logic intact

* @param outState */ @suppresslint ("MissingSuperCall") @override protected void onSaveInstanceState(Bundle outState) {/* Record current position */ outstate.putint ("position", mPosition);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        mPosition = savedInstanceState.getInt("position");
        selectedFragment(mPosition);
    }

Copy the code

2 white

2.1 Trigger Cause

If you do not use getChildFragmentManager() when there is a Fragment inside a Fragment, the Fragment cannot be retrieved after the Activity resumes, resulting in a blank screen.

2.1 Solutions

Fragment When nested fragments, use getChildFragmentManager() to get the transaction