简体   繁体   中英

Remove fragment from backstack in nested fragments android

I have a MainActivity in which I have Added a Fragment ==> BenefitsFragment in BenefintsFragment there is a RelativeLayout

<RelativeLayout
        android:visibility="gone"
        android:background="@android:color/white"
        android:id="@+id/benefitContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent">


    </RelativeLayout>

I am adding another fragment like

   browseBtn.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    RelativeLayout mLayout = (RelativeLayout) view.findViewById(R.id.benefitContainer);
                    mLayout.setVisibility(View.VISIBLE);
                    getChildFragmentManager().beginTransaction()
                            .add(R.id.benefitContainer, new ConfirmPinFragment()).commitNow();
                }
            });

In my new ConfirmPinFragment I am trying to go back to old BenefitsFragment as

    backBtn.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    getChildFragmentManager().popBackStack();
                }
            });

However this popBackStack not working, if i try to remove using

        getChildFragmentManager().beginTransaction().remove(ConfirmPinFragment.this).commitNow();

It crashes saying

java.lang.IllegalStateException: FragmentManager is already executing transactions

There are two things you need to do for this to work. But first of all there is really no need for commitNow() . The first thing you need to do is to add the fragment you want to go back to into the back stack during the transaction:

browseBtn.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            RelativeLayout mLayout = (RelativeLayout) view.findViewById(R.id.benefitContainer);
            mLayout.setVisibility(View.VISIBLE);
            getChildFragmentManager().beginTransaction()
                    .add(R.id.benefitContainer, new ConfirmPinFragment())
                    .addToBackStack("benefits fragment").commit();
        }
    });

and when you go back use the getFragmentManager() instead of getChildFragmentManager() because you actually want the fragment manager that holds this fragment. Child fragment manager is the manager that manages the fragments inside this fragment.

backBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            getFragmentManager().popBackStack();
        }
    });

Hope this helps.

Be careful when using commitNow() , the fragment that you add won't be added into backstack. See this answer and this blog post for more info.

If you want to use backstack you should use commit() with addToBackStack() instead of commitNow()

The main reason why commitNow() is not adding into backstack is commitNow() will execute the transaction synchronously, if it'll added into backstack the transaction can broke the backstack order if there are another pending asynchronous transactions.

You add to the back state from the FragmentTransaction and remove from the backstack using FragmentManager pop methods:

FragmentManager manager = getActivity().getSupportFragmentManager();
FragmentTransaction trans = manager.beginTransaction();
trans.remove(myFrag);
trans.commit();
manager.popBackStack();

Using Kotlin and fragment-ktx using this one:

In your gradle:

implementation "androidx.fragment:fragment-ktx:$androidXFragmentKtxVersion"

In your Fragment

childFragmentManager
      .findFragmentByTag(YOUR_TAG)?.let { fragment ->
        childFragmentManager.commit(allowStateLoss = true) {
          remove(fragment)
        }
      }

If you are not using childFragmentManager use requireActivity().supportFragmentManage r instead

requireActivity().supportFragmentManage
          .findFragmentByTag(YOUR_TAG)?.let { fragment ->
            requireActivity().supportFragmentManage.commit(allowStateLoss = true) {
              remove(fragment)
            }
      }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM