java.lang.IllegalStateException:键f0:index 1不再存在片段

时间:2017-08-17 12:08:06

标签: android android-fragments

我在Activity中有几个片段。在做了一些过程后,我使用下面的代码关闭片段。

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

9 个答案:

答案 0 :(得分:3)

对于ViewPager2,只需使用viewPager.setSaveEnabled(false);

答案 1 :(得分: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;

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

您的堆栈跟踪显示您正在使用ViewPager并自行操纵Backstack。

这可能不是一个好主意 - 让你的ViewPager管理后台(它做得好)或自己完全管理它。

请注意,在自己管理backstack时,您必须考虑恢复实例状态(堆栈跟踪中的哪些功能)和Fragment lifecycle

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

答案 4 :(得分: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();
        }

答案 5 :(得分:0)

首先,您不需要致电getActivity().getSupportFragmentManager()getFragmentManager()就足以致电FragmentManager

如果你在支持片段,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)

希望有所帮助:)

答案 6 :(得分:0)

在ViewPager适配器中,覆盖@Service public class SubjectDAO { @Autowired SubjectRepository subjectRepository; //to save a subject public Subject save(Subject subject){ return subjectRepository.save(subject); } //to search all subjects public List<Subject> findAll(){ return subjectRepository.findAll(); } //get a subject by id public Subject findById(Long id){ return subjectRepository.findById(id).orElse(null); } //delete a subject public void delete(Long id){ subjectRepository.deleteById(id); } }

restoreState(state, loader)

答案 7 :(得分: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()
        }
    }
}

答案 8 :(得分:0)

何时发生崩溃?

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

如何修复?

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

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

更多详情here