java.lang.IllegalStateException:键 f0 的片段不再存在:索引 1

问题描述 投票:0回答:11

我的活动中有几个片段。完成一些过程后,我使用下面的代码关闭片段。

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

但是在 popBackStackImmediate() 线上它抛出了错误

    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)

没有其他崩溃会关闭片段。我找不到这个问题的确切解决方案。请帮我解决这个问题。

编辑:

我正在使用下面的函数来调用片段。

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();
    }
}
android android-fragments
11个回答
25
投票

对于 ViewPager2 只需使用

viewPager.setSaveEnabled(false);


3
投票

在 ViewPager 适配器中,覆盖

restoreState(state, loader)

    @Override
    public void restoreState(final Parcelable state, final ClassLoader loader) {
        try {
            super.restoreState(state, loader);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

0
投票

请按照以下步骤添加活动中的片段

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

使用此代码从片段中调用

popBackStack()

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

确保您导入正确的片段类

import android.support.v4.app.Fragment;

0
投票

在 Fragment 类中添加以下代码,根据 doc,它返回 Transition,用于在 Fragment 准备关闭时将视图移出场景。

@Override
    public Object getReturnTransition() {
        return super.getReturnTransition();
    }

0
投票

您的堆栈跟踪显示您正在使用

ViewPager
并自己操作后堆栈。

这可能不是一个好主意 - 要么让你的

ViewPager
管理后退堆栈(它做得很好),要么完全你自己管理。

请注意,在自己管理后台堆栈时,您必须考虑恢复实例状态(堆栈跟踪中的功能)和Fragment 生命周期

这意味着在内存不足的情况下,您的 Activity 和 Fragments 将停止。如果您没有正确保存实例状态,当它们重新启动时,您将收到类似上述错误。如果您的片段的工作流程很简单,您可以使用

ViewPager
来避免所有这些。


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();
        }

0
投票

首先,你不需要打电话

getActivity().getSupportFragmentManager()
getFragmentManager()
就可以拨打
FragmentManager

如果你在 Support Fragment getFragmentManager() 会给你

supportFragmentManager()
或者它会给你 app.Fragment Manager

如果你在ViewPager内部调用PopBackstack,它将不起作用。如果您在另一个片段中使用

viewPager
。您应该仅在父片段中调用
popBackstack
。不在
viewPager
中。

尝试下面的代码,它将根据返回堆栈名称清除堆栈。

getFragmentManager.popBackStackImmediate(YourBackStackName, FragmentManager.POP_BACK_STACK_INCLUSIVE)

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

希望有帮助:)


0
投票

重写 viewPager 中的 RestoreState 方法对我有用。

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

这是我的视图寻呼机的最终代码

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
投票

此崩溃何时发生?

  • 当ViewPager包裹Fragment时,Fragment内还有ViewPager包裹Fragment。
  • 当外层Fragment或内层Adapter继承FragmentStatePagerAdapter,或者两者都继承FragmentStatePagerAdapter时。

如何修复?

在报错的Fragment的Adapter中重写以下方法,返回null。

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

更多详情这里


0
投票

viewPagerAdapter
(在 ViewPager2->restorePendingState->restoreState 中)变为 null 时,会发生这种情况,但 ViewPager2->restorePendingState 仍然收到它。

尝试在此行标记停止断点或重新安装应用程序

void 位于 androidx.viewpager2.widget.ViewPager2

private void restorePendingState() {
    ...
    Adapter<?> adapter = getAdapter();
    if (adapter == null) {
        return;
    }
    ...
}

0
投票

使用

viewPager.setSaveEnabled(false)
有效,但保存视图的状态将被禁用,我不希望发生这种情况。我想在可能的情况下恢复状态,并且在引发异常的情况下只需捕获它而不恢复状态。 您无法覆盖 ViewPager 适配器中的
restoreState(state, loader)
,因为该方法是最终方法,但是您可以在 Activity 的
onStart
方法中捕获异常:

 @Override
    protected void onStart() {
        try {
            super.onStart();
        }catch (IllegalStateException e) {
            e.printStackTrace();
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.