8

I am having couple of fragment in an Activity. After doing some process I am closing the fragment using the below code.

if (getActivity().getSupportFragmentManager().getBackStackEntryCount() > 0) {
                        getActivity().getSupportFragmentManager().popBackStackImmediate();
}

But on line popBackStackImmediate() its throwing the error

    Process: com.TestProject.testpro, PID: 17966
 java.lang.IllegalStateException: Fragment no longer exists for key f0: index 1
     at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:879)
     at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:215)
     at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:1481)
     at android.view.View.dispatchRestoreInstanceState(View.java:14746)
     at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3121)
     at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3127)
     at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3127)
     at android.view.View.restoreHierarchyState(View.java:14724)
     at android.support.v4.app.Fragment.restoreViewState(Fragment.java:475)
     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1329)
     at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1528)
     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1595)
     at android.support.v4.app.BackStackRecord.executePopOps(BackStackRecord.java:807)
     at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2360)
     at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2149)
     at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2103)
     at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:823)
     at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:776)
     at com.TestProject.testpro.application.fragments.WFMUpgradeToAffinityFragmentAN$WFMStoreProfileIdReceiver.onReceive(WFMUpgradeToAffinityFragmentAN.java:1064)
     at android.support.v4.content.LocalBroadcastManager.executePendingBroadcasts(LocalBroadcastManager.java:297)
     at android.support.v4.content.LocalBroadcastManager.access$000(LocalBroadcastManager.java:46)
     at android.support.v4.content.LocalBroadcastManager$1.handleMessage(LocalBroadcastManager.java:116)
     at android.os.Handler.dispatchMessage(Handler.java:102)
     at android.os.Looper.loop(Looper.java:148)
     at android.app.ActivityThread.main(ActivityThread.java:5417)
     at java.lang.reflect.Method.invoke(Native Method)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

There is no other crash which close the fragment. I cant find the exact solution for this issue. Please help me on this.

Edited:

I am using the below function to call the fragment.

void showContentFragment(Fragment newFragment, String backStackName) {
    //Log.e(TAG, "showContentFragment- " + "BackstackName: "+ backStackName);
    FragmentManager mFragmentManager = getActivity().getSupportFragmentManager();
    if (newFragment != null) {
        //updateNavigation(backStackName);
        FragmentTransaction ft = mFragmentManager.beginTransaction();
        ft.replace(R.id.fragment_container, newFragment);
        if (backStackName != null && !backStackName.isEmpty()) {
            ft.addToBackStack(backStackName);
        }

        ft.commit();
    }
}
Sniper
  • 2,412
  • 11
  • 44
  • 49

10 Answers10

25

For ViewPager2 simply use viewPager.setSaveEnabled(false);

Andoctorey
  • 728
  • 9
  • 11
  • Yes, it works, I think, it was gotten from https://stackoverflow.com/questions/59486504/fragment-no-longer-exists-for-key-fragmentstateadapter-with-viewpager2. – CoolMind Feb 09 '21 at 15:39
2

In the ViewPager Adapter, override restoreState(state, loader)

    @Override
    public void restoreState(final Parcelable state, final ClassLoader loader) {
        try {
            super.restoreState(state, loader);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • 2
    unfortunately, this will not work for ViewPager2. restoreState is declared as final. – JE42 Aug 17 '20 at 09:43
0

Please follow this steps to add fragments from your activity

 getSupportFragmentManager().beginTransaction()
                .replace(R.id.frame, yourFragment, yourFragment.class.getSimpleName()).addToBackStack(yourFragment.class.getSimpleName())
                .commit();

using this code for calling popBackStack() from your fragment

    if (getFragmentManager().getBackStackEntryCount() > 0) {
                        getFragmentManager().popBackStack();
}

Make sure that you are importing right fragment class

import android.support.v4.app.Fragment;
Vinayak B
  • 4,430
  • 4
  • 28
  • 58
0

add Below code in your Fragment classes , according to doc it returns the Transition to use to move Views out of the Scene when the Fragment is preparing to close.

@Override
    public Object getReturnTransition() {
        return super.getReturnTransition();
    }
Omar Dhanish
  • 885
  • 7
  • 18
0

Your stacktrace shows you are using both a ViewPager and manipulating the backstack yourself.

This is probably not a good idea - either let your ViewPager manage the backstack (which it does well) or manage it entirely yourself.

Note that in managing the backstack yourself you will have to account for restoring instance state (which features in your stacktrace) and the Fragment lifecycle.

This means in conditions of low memory your Activity and Fragments will be stopped. If you have not saved the instance state correctly, when they are restarted you will get errors like the above one. If the workflow of your Fragments is simple, you can avoid all of this by using a ViewPager.

David Rawson
  • 20,912
  • 7
  • 88
  • 124
0
public void showContentFragment(Fragment fragment, Bundle bundle, boolean addToBackStack) {
        if (bundle != null)
            fragment.setArguments(bundle);

        tag = fragment.getClass().getSimpleName();
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right);
        ft.replace(R.id.container_internal, fragment, tag);
        fragment.setRetainInstance(true); // IMPORTANT

        if (addToBackStack)
            ft.addToBackStack(tag);

        try {
            ft.commit();

        } catch (Exception ex) {
            ex.printStackTrace();
            ft.commitAllowingStateLoss();
        }
kartic chaudhary
  • 206
  • 3
  • 12
0

First, you don't need to call getActivity().getSupportFragmentManager(). getFragmentManager() is enough to call FragmentManager.

If you are in Support Fragment getFragmentManager() will give you supportFragmentManager() or it will give you app.Fragment Manager.

If you are calling the PopBackstack inside the ViewPager, it won't work. If you are using viewPager inside another fragment. you should call popBackstack only in the parent fragment. Not in the viewPager.

Try the below code it will clear the stack according to the back stack name.

getFragmentManager.popBackStackImmediate(YourBackStackName, FragmentManager.POP_BACK_STACK_INCLUSIVE)

Docs: https://developer.android.com/reference/android/app/FragmentManager.html#popBackStackImmediate(java.lang.String, int)

Hope it helps :)

Bhuvanesh BS
  • 13,474
  • 12
  • 40
  • 66
0

Overriding restoreState method in my viewPager worked for me.

override fun restoreState(state: Parcelable?, loader: ClassLoader?) {
        try {
            super.restoreState(state, loader)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

Here is the final code of my view pager

class MenuTabAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
    private val mFragmentList = ArrayList<Fragment>()
    private val mFragmentTitleList = ArrayList<String>()
    private var mCurrentPosition = -1
    override fun getItem(position: Int): Fragment {
        return mFragmentList[position]
    }

    override fun getCount(): Int {
        return mFragmentList.size
    }

    fun addFragment(fragment: Fragment, title: String) {
        mFragmentList.add(fragment)
        mFragmentTitleList.add(title)
    }

    override fun getPageTitle(position: Int): CharSequence? {
        return mFragmentTitleList[position]
    }

    override fun setPrimaryItem(container: ViewGroup, position: Int, `object`: Any) {
        super.setPrimaryItem(container, position, `object`)


        if (position !== mCurrentPosition && container is HeightWrappingViewPager) {
            val fragment = `object` as Fragment
            if (fragment?.view != null) {
                mCurrentPosition = position
                container.requestLayout()
            }
        }
    }

    override fun restoreState(state: Parcelable?, loader: ClassLoader?) {
        try {
            super.restoreState(state, loader)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}
0

When this crash occurs?

  • When ViewPager wraps Fragment, and there is ViewPager wraps Fragment inside Fragment.
  • When the outer Fragment or the inner Adapter inherits FragmentStatePagerAdapter, or both inherit FragmentStatePagerAdapter.

How to fix?

Override the following method in the Adapter of the Fragment that reported the error and return null.

@Override  
public Parcelable saveState() {  
    return null;  
}

More details here.

Changer
  • 351
  • 1
  • 3
  • 12
0

This happens when viewPagerAdapter(in ViewPager2->restorePendingState->restoreState) became null, but ViewPager2->restorePendingState still received it.

Try to mark stop breakpoint at this line or reinstall app

void is in androidx.viewpager2.widget.ViewPager2

private void restorePendingState() {
    ...
    Adapter<?> adapter = getAdapter();
    if (adapter == null) {
        return;
    }
    ...
}
Evgenii
  • 105
  • 1
  • 9